cleaning hard 2
This commit is contained in:
parent
35d4e37d79
commit
4046e03261
@ -1,52 +1,31 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Inter } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import { headers } from "next/headers";
|
||||
import { getServerSession } from "next-auth/next";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
|
||||
import { Providers } from "@/components/providers";
|
||||
import { LayoutWrapper } from "@/components/layout/layout-wrapper";
|
||||
import { warmupRedisCache } from '@/lib/redis';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
// Dynamically import heavy components with proper typing
|
||||
const Providers = dynamic(() => import('@/components/providers'), {
|
||||
ssr: true,
|
||||
loading: () => <div className="min-h-screen bg-background"></div>
|
||||
});
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
|
||||
// Warm up Redis connection during app initialization
|
||||
warmupRedisCache().catch(console.error);
|
||||
export const metadata = {
|
||||
title: "Neah Front",
|
||||
description: "Neah Front Application",
|
||||
};
|
||||
|
||||
export default async function RootLayout({
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
// Try to get the session, but handle potential errors gracefully
|
||||
let session = null;
|
||||
let sessionError = false;
|
||||
|
||||
try {
|
||||
session = await getServerSession(authOptions);
|
||||
} catch (error) {
|
||||
console.error("Error getting server session:", error);
|
||||
sessionError = true;
|
||||
}
|
||||
|
||||
const headersList = await headers();
|
||||
const pathname = headersList.get("x-pathname") || "";
|
||||
const isSignInPage = pathname === "/signin";
|
||||
|
||||
// If we're on the signin page and there was a session error,
|
||||
// don't pass the session to avoid refresh attempts
|
||||
const safeSession = isSignInPage && sessionError ? null : session;
|
||||
|
||||
return (
|
||||
<html lang="fr">
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body className={inter.className}>
|
||||
<Providers session={safeSession}>
|
||||
<LayoutWrapper
|
||||
isSignInPage={isSignInPage}
|
||||
isAuthenticated={!!session && !sessionError}
|
||||
>
|
||||
{children}
|
||||
</LayoutWrapper>
|
||||
<Providers>
|
||||
{children}
|
||||
</Providers>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
65
app/page.tsx
65
app/page.tsx
@ -1,13 +1,24 @@
|
||||
"use client";
|
||||
|
||||
import { QuoteCard } from "@/components/quote-card";
|
||||
import { Calendar } from "@/components/calendar";
|
||||
import { News } from "@/components/news";
|
||||
import { Duties } from "@/components/flow";
|
||||
import { Email } from "@/components/email";
|
||||
import { Parole } from "@/components/parole";
|
||||
import { Suspense, lazy, useEffect, useState } from "react";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
// Dynamic imports with lazy loading
|
||||
const QuoteCard = lazy(() => import("@/components/quote-card").then(mod => ({ default: mod.QuoteCard })));
|
||||
const Calendar = lazy(() => import("@/components/calendar").then(mod => ({ default: mod.Calendar })));
|
||||
const News = lazy(() => import("@/components/news").then(mod => ({ default: mod.News })));
|
||||
const Duties = lazy(() => import("@/components/flow").then(mod => ({ default: mod.Duties })));
|
||||
const Email = lazy(() => import("@/components/email").then(mod => ({ default: mod.Email })));
|
||||
const Parole = lazy(() => import("@/components/parole").then(mod => ({ default: mod.Parole })));
|
||||
|
||||
// Skeleton loaders for each component
|
||||
const QuoteCardSkeleton = () => (
|
||||
<div className="bg-gray-100 animate-pulse rounded-lg h-72 w-full"></div>
|
||||
);
|
||||
|
||||
const GenericSkeleton = () => (
|
||||
<div className="bg-gray-100 animate-pulse rounded-lg h-96 w-full"></div>
|
||||
);
|
||||
|
||||
export default function Home() {
|
||||
const { data: session, status } = useSession();
|
||||
@ -31,28 +42,40 @@ export default function Home() {
|
||||
<main className="h-screen overflow-auto">
|
||||
<div className="container mx-auto p-4 mt-12">
|
||||
{/* First row */}
|
||||
<div className="grid grid-cols-12 gap-4 mb-4">
|
||||
<div className="col-span-3">
|
||||
<QuoteCard />
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-4">
|
||||
<div>
|
||||
<Suspense fallback={<QuoteCardSkeleton />}>
|
||||
<QuoteCard />
|
||||
</Suspense>
|
||||
</div>
|
||||
<div className="col-span-3">
|
||||
<Calendar limit={5} showMore={true} showRefresh={true} />
|
||||
<div>
|
||||
<Suspense fallback={<GenericSkeleton />}>
|
||||
<Calendar limit={5} showMore={true} showRefresh={true} />
|
||||
</Suspense>
|
||||
</div>
|
||||
<div className="col-span-3">
|
||||
<News />
|
||||
<div>
|
||||
<Suspense fallback={<GenericSkeleton />}>
|
||||
<News />
|
||||
</Suspense>
|
||||
</div>
|
||||
<div className="col-span-3">
|
||||
<Duties />
|
||||
<div>
|
||||
<Suspense fallback={<GenericSkeleton />}>
|
||||
<Duties />
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Second row */}
|
||||
<div className="grid grid-cols-12 gap-4">
|
||||
<div className="col-span-6">
|
||||
<Email />
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<Suspense fallback={<GenericSkeleton />}>
|
||||
<Email />
|
||||
</Suspense>
|
||||
</div>
|
||||
<div className="col-span-6">
|
||||
<Parole />
|
||||
<div>
|
||||
<Suspense fallback={<GenericSkeleton />}>
|
||||
<Parole />
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -36,6 +36,21 @@ import {
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { format } from 'date-fns';
|
||||
import { fr } from 'date-fns/locale';
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
// Dynamically import heavy components
|
||||
const UserMenu = dynamic(() => import("./navbar/user-menu"), {
|
||||
ssr: true,
|
||||
loading: () => <div className="w-10 h-10 rounded-full bg-gray-200" />
|
||||
});
|
||||
|
||||
const SidebarComponent = dynamic(() => import("./sidebar").then(mod => ({ default: mod.Sidebar })), {
|
||||
ssr: false
|
||||
});
|
||||
|
||||
const NavigationItems = dynamic(() => import("./navbar/navigation-items"), {
|
||||
ssr: true
|
||||
});
|
||||
|
||||
const requestNotificationPermission = async () => {
|
||||
try {
|
||||
@ -220,178 +235,43 @@ export function MainNav() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="fixed top-0 left-0 right-0 z-50 bg-black">
|
||||
<div className="flex items-center justify-between px-4 py-1">
|
||||
{/* Left side */}
|
||||
<div className="flex items-center space-x-4">
|
||||
<button
|
||||
onClick={() => setIsSidebarOpen(true)}
|
||||
className="text-white/80 hover:text-white"
|
||||
>
|
||||
<Menu className="w-5 h-5" />
|
||||
</button>
|
||||
<Link href='/'>
|
||||
<header className="sticky top-0 z-40 w-full bg-white dark:bg-gray-950 border-b">
|
||||
<div className="container flex h-16 items-center px-4 sm:px-8">
|
||||
<button
|
||||
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
|
||||
className="mr-4 p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-md"
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
<Menu className="h-5 w-5" />
|
||||
</button>
|
||||
|
||||
<div className="flex items-center">
|
||||
<Link href="/" className="flex items-center">
|
||||
<Image
|
||||
src='/Neahv2 logo W.png'
|
||||
alt='Neah Logo'
|
||||
width={40}
|
||||
height={13}
|
||||
className='text-white'
|
||||
src="/logo.png"
|
||||
alt="Neah Logo"
|
||||
width={28}
|
||||
height={28}
|
||||
className="mr-2"
|
||||
/>
|
||||
</Link>
|
||||
<Link href='/agenda' className='text-white/80 hover:text-white'>
|
||||
<Calendar className='w-5 h-5' />
|
||||
</Link>
|
||||
<Link href='/timetracker' className='text-white/80 hover:text-white'>
|
||||
<Clock className='w-5 h-5' />
|
||||
<span className="sr-only">TimeTracker</span>
|
||||
</Link>
|
||||
<Link href='/notes' className='text-white/80 hover:text-white'>
|
||||
<PenLine className='w-5 h-5' />
|
||||
<span className="sr-only">Notes</span>
|
||||
</Link>
|
||||
<Link href='/alma' className='text-white/80 hover:text-white'>
|
||||
<Robot className='w-5 h-5' />
|
||||
<span className="sr-only">ALMA</span>
|
||||
</Link>
|
||||
<Link href='/vision' className='text-white/80 hover:text-white'>
|
||||
<Video className='w-5 h-5' />
|
||||
<span className="sr-only">Vision</span>
|
||||
</Link>
|
||||
<Link href='/observatory' className='text-white/80 hover:text-white'>
|
||||
<Telescope className='w-5 h-5' />
|
||||
<span className="sr-only">Observatory</span>
|
||||
</Link>
|
||||
<Link href='/radio' className='text-white/80 hover:text-white'>
|
||||
<RadioIcon className='w-5 h-5' />
|
||||
<span className="sr-only">Radio</span>
|
||||
</Link>
|
||||
<Link href='/announcement' className='text-white/80 hover:text-white'>
|
||||
<Megaphone className='w-5 h-5' />
|
||||
<span className="sr-only">Announcement</span>
|
||||
<span className="font-bold text-xl">Neah</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Right side */}
|
||||
<div className="flex items-center space-x-8">
|
||||
{/* Date and Time with smaller text */}
|
||||
<div className="text-white/80 text-sm">
|
||||
<span className="mr-2">{formattedDate}</span>
|
||||
<span>{formattedTime}</span>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href='/notifications'
|
||||
className='text-white/80 hover:text-white'
|
||||
>
|
||||
<Bell className='w-5 h-5' />
|
||||
</Link>
|
||||
|
||||
{status === "authenticated" && session?.user ? (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger className="outline-none">
|
||||
<div className="w-8 h-8 rounded-full bg-blue-600 flex items-center justify-center text-white cursor-pointer hover:bg-blue-700 transition-colors">
|
||||
{getUserInitials()}
|
||||
</div>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-56 bg-black/90 border-gray-700">
|
||||
<DropdownMenuLabel className="text-white/80">
|
||||
<div className="flex items-center justify-between">
|
||||
<span>{getDisplayName()}</span>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger className="outline-none">
|
||||
<div className="flex items-center space-x-1 text-sm">
|
||||
<Circle className={`h-3 w-3 ${statusConfig[userStatus].color}`} />
|
||||
<span className="text-gray-400">{statusConfig[userStatus].label}</span>
|
||||
</div>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="bg-black/90 border-gray-700">
|
||||
<DropdownMenuItem
|
||||
className="text-white/80 hover:text-white hover:bg-black/50 cursor-pointer"
|
||||
onClick={() => handleStatusChange('online')}
|
||||
>
|
||||
<Circle className="h-3 w-3 text-green-500 mr-2" />
|
||||
<span>Online</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
className="text-white/80 hover:text-white hover:bg-black/50 cursor-pointer"
|
||||
onClick={() => handleStatusChange('busy')}
|
||||
>
|
||||
<Circle className="h-3 w-3 text-orange-500 mr-2" />
|
||||
<span>Busy</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
className="text-white/80 hover:text-white hover:bg-black/50 cursor-pointer"
|
||||
onClick={() => handleStatusChange('away')}
|
||||
>
|
||||
<Circle className="h-3 w-3 text-gray-500 mr-2" />
|
||||
<span>Away</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator className="bg-gray-700" />
|
||||
{visibleMenuItems.map((item) => (
|
||||
<DropdownMenuItem
|
||||
key={item.title}
|
||||
className="text-white/80 hover:text-white hover:bg-black/50 cursor-pointer"
|
||||
onClick={() => window.location.href = item.href}
|
||||
>
|
||||
<item.icon className="mr-2 h-4 w-4" />
|
||||
<span>{item.title}</span>
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
<DropdownMenuItem
|
||||
className="text-white/80 hover:text-white hover:bg-black/50 cursor-pointer"
|
||||
onClick={async () => {
|
||||
try {
|
||||
// First sign out from NextAuth
|
||||
await signOut({
|
||||
callbackUrl: '/signin',
|
||||
redirect: false
|
||||
});
|
||||
|
||||
// Then redirect to Keycloak logout with proper parameters
|
||||
const keycloakLogoutUrl = new URL(
|
||||
`${process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER}/protocol/openid-connect/logout`
|
||||
);
|
||||
|
||||
// Add required parameters
|
||||
keycloakLogoutUrl.searchParams.append(
|
||||
'post_logout_redirect_uri',
|
||||
window.location.origin
|
||||
);
|
||||
keycloakLogoutUrl.searchParams.append(
|
||||
'id_token_hint',
|
||||
session?.accessToken || ''
|
||||
);
|
||||
|
||||
// Redirect to Keycloak logout
|
||||
window.location.href = keycloakLogoutUrl.toString();
|
||||
} catch (error) {
|
||||
console.error('Error during logout:', error);
|
||||
// Fallback to simple redirect if something goes wrong
|
||||
window.location.href = '/signin';
|
||||
}
|
||||
}}
|
||||
>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
<span>Déconnexion</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
) : (
|
||||
<div className='cursor-pointer text-white/80 hover:text-white'>
|
||||
<span onClick={() => signIn("keycloak", { callbackUrl: "/" })}>
|
||||
Login
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="ml-auto flex items-center space-x-4">
|
||||
<NavigationItems session={session} />
|
||||
<UserMenu session={session} status={status} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
|
||||
</header>
|
||||
|
||||
{isSidebarOpen && (
|
||||
<SidebarComponent
|
||||
isOpen={isSidebarOpen}
|
||||
onClose={() => setIsSidebarOpen(false)}
|
||||
session={session}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
78
components/navbar/navigation-items.tsx
Normal file
78
components/navbar/navigation-items.tsx
Normal file
@ -0,0 +1,78 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Calendar,
|
||||
MessageSquare,
|
||||
Bell,
|
||||
Clock,
|
||||
PenLine,
|
||||
Telescope
|
||||
} from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { Session } from "next-auth";
|
||||
|
||||
interface NavigationItemsProps {
|
||||
session: Session | null;
|
||||
}
|
||||
|
||||
export default function NavigationItems({ session }: NavigationItemsProps) {
|
||||
const isAuthenticated = !!session?.user;
|
||||
|
||||
// Only show navigation items if user is authenticated
|
||||
if (!isAuthenticated) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
href: '/agenda',
|
||||
icon: Calendar,
|
||||
label: 'Calendar'
|
||||
},
|
||||
{
|
||||
href: '/messages',
|
||||
icon: MessageSquare,
|
||||
label: 'Messages'
|
||||
},
|
||||
{
|
||||
href: '/timetracker',
|
||||
icon: Clock,
|
||||
label: 'Time Tracker'
|
||||
},
|
||||
{
|
||||
href: '/notes',
|
||||
icon: PenLine,
|
||||
label: 'Notes'
|
||||
},
|
||||
{
|
||||
href: '/observatory',
|
||||
icon: Telescope,
|
||||
label: 'Observatory'
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="hidden md:flex items-center space-x-2">
|
||||
{navItems.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800"
|
||||
aria-label={item.label}
|
||||
>
|
||||
<item.icon className="h-5 w-5" />
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href="/notifications"
|
||||
className="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800"
|
||||
aria-label="Notifications"
|
||||
>
|
||||
<Bell className="h-5 w-5" />
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
}
|
||||
181
components/navbar/user-menu.tsx
Normal file
181
components/navbar/user-menu.tsx
Normal file
@ -0,0 +1,181 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Circle, LogOut } from "lucide-react";
|
||||
import { useSession, signIn, signOut } from "next-auth/react";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Session } from "next-auth";
|
||||
|
||||
interface UserMenuProps {
|
||||
session: Session | null;
|
||||
status: "loading" | "authenticated" | "unauthenticated";
|
||||
}
|
||||
|
||||
const requestNotificationPermission = async () => {
|
||||
try {
|
||||
const permission = await Notification.requestPermission();
|
||||
return permission === "granted";
|
||||
} catch (error) {
|
||||
console.error("Error requesting notification permission:", error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export default function UserMenu({ session, status }: UserMenuProps) {
|
||||
const [userStatus, setUserStatus] = useState<'online' | 'busy' | 'away'>('online');
|
||||
|
||||
// Get user initials
|
||||
const getUserInitials = () => {
|
||||
if (session?.user?.name) {
|
||||
// Split the full name and get initials
|
||||
const names = session.user.name.split(' ');
|
||||
if (names.length >= 2) {
|
||||
return `${names[0][0]}${names[names.length - 1][0]}`.toUpperCase();
|
||||
}
|
||||
// If only one name, use first two letters
|
||||
return names[0].slice(0, 2).toUpperCase();
|
||||
}
|
||||
return "?";
|
||||
};
|
||||
|
||||
// Function to get display name
|
||||
const getDisplayName = () => {
|
||||
return session?.user?.name || "User";
|
||||
};
|
||||
|
||||
// Status configurations
|
||||
const statusConfig = {
|
||||
online: {
|
||||
color: 'text-green-500',
|
||||
label: 'Online',
|
||||
notifications: true
|
||||
},
|
||||
busy: {
|
||||
color: 'text-orange-500',
|
||||
label: 'Busy',
|
||||
notifications: false
|
||||
},
|
||||
away: {
|
||||
color: 'text-gray-500',
|
||||
label: 'Away',
|
||||
notifications: false
|
||||
},
|
||||
};
|
||||
|
||||
// Handle status change
|
||||
const handleStatusChange = async (newStatus: 'online' | 'busy' | 'away') => {
|
||||
setUserStatus(newStatus);
|
||||
|
||||
if (newStatus !== 'online') {
|
||||
const hasPermission = await requestNotificationPermission();
|
||||
|
||||
if (hasPermission) {
|
||||
// Disable notifications
|
||||
if ('serviceWorker' in navigator) {
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
await registration.pushManager.getSubscription()?.then(subscription => {
|
||||
if (subscription) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Re-enable notifications if going back online
|
||||
requestNotificationPermission();
|
||||
}
|
||||
};
|
||||
|
||||
if (status === "authenticated" && session?.user) {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger className="outline-none">
|
||||
<div className="w-10 h-10 rounded-full bg-blue-600 flex items-center justify-center text-white cursor-pointer hover:bg-blue-700 transition-colors">
|
||||
{getUserInitials()}
|
||||
</div>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-56">
|
||||
<DropdownMenuLabel>
|
||||
<div className="flex items-center justify-between">
|
||||
<span>{getDisplayName()}</span>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger className="outline-none">
|
||||
<div className="flex items-center space-x-1 text-sm">
|
||||
<Circle className={`h-3 w-3 ${statusConfig[userStatus].color}`} />
|
||||
<span className="text-gray-400">{statusConfig[userStatus].label}</span>
|
||||
</div>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem onClick={() => handleStatusChange('online')}>
|
||||
<Circle className="h-3 w-3 text-green-500 mr-2" />
|
||||
<span>Online</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleStatusChange('busy')}>
|
||||
<Circle className="h-3 w-3 text-orange-500 mr-2" />
|
||||
<span>Busy</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleStatusChange('away')}>
|
||||
<Circle className="h-3 w-3 text-gray-500 mr-2" />
|
||||
<span>Away</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
onClick={async () => {
|
||||
try {
|
||||
// First sign out from NextAuth
|
||||
await signOut({
|
||||
callbackUrl: '/signin',
|
||||
redirect: false
|
||||
});
|
||||
|
||||
// Then redirect to Keycloak logout with proper parameters
|
||||
const keycloakLogoutUrl = new URL(
|
||||
`${process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER}/protocol/openid-connect/logout`
|
||||
);
|
||||
|
||||
// Add required parameters
|
||||
keycloakLogoutUrl.searchParams.append(
|
||||
'post_logout_redirect_uri',
|
||||
window.location.origin
|
||||
);
|
||||
keycloakLogoutUrl.searchParams.append(
|
||||
'id_token_hint',
|
||||
session?.accessToken || ''
|
||||
);
|
||||
|
||||
// Redirect to Keycloak logout
|
||||
window.location.href = keycloakLogoutUrl.toString();
|
||||
} catch (error) {
|
||||
console.error('Error during logout:', error);
|
||||
// Fallback to simple redirect if something goes wrong
|
||||
window.location.href = '/signin';
|
||||
}
|
||||
}}
|
||||
>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
<span>Sign out</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="cursor-pointer">
|
||||
<span onClick={() => signIn("keycloak", { callbackUrl: "/" })}>
|
||||
Login
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,16 +1,19 @@
|
||||
"use client";
|
||||
|
||||
import { SessionProvider } from "next-auth/react";
|
||||
import { ThemeProvider } from "next-themes";
|
||||
|
||||
interface ProvidersProps {
|
||||
children: React.ReactNode;
|
||||
session: any;
|
||||
session?: any;
|
||||
}
|
||||
|
||||
export function Providers({ children, session }: ProvidersProps) {
|
||||
export default function Providers({ children, session }: ProvidersProps) {
|
||||
return (
|
||||
<SessionProvider session={session} refetchInterval={5 * 60}>
|
||||
{children}
|
||||
</SessionProvider>
|
||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
||||
<SessionProvider session={session} refetchInterval={5 * 60}>
|
||||
{children}
|
||||
</SessionProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
@ -1,3 +1,7 @@
|
||||
const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
||||
enabled: process.env.ANALYZE === 'true',
|
||||
});
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
webpack: (config, { isServer }) => {
|
||||
@ -9,6 +13,12 @@ const nextConfig = {
|
||||
stream: require.resolve('stream-browserify'),
|
||||
util: require.resolve('util/'),
|
||||
};
|
||||
|
||||
// Add module concatenation for better tree shaking
|
||||
config.optimization.concatenateModules = true;
|
||||
|
||||
// Enable deterministic ids for better caching
|
||||
config.optimization.moduleIds = 'deterministic';
|
||||
}
|
||||
return config;
|
||||
},
|
||||
@ -19,13 +29,27 @@ const nextConfig = {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
images: {
|
||||
unoptimized: true,
|
||||
domains: ['espace.slm-lab.net', 'connect.slm-lab.net'],
|
||||
formats: ['image/avif', 'image/webp'],
|
||||
},
|
||||
experimental: {
|
||||
webpackBuildWorker: true,
|
||||
parallelServerBuildTraces: true,
|
||||
parallelServerCompiles: true,
|
||||
optimizeCss: true,
|
||||
serverMinification: true,
|
||||
},
|
||||
// Enable aggressive compression
|
||||
compress: true,
|
||||
// Enable production source maps for better performance debugging
|
||||
productionBrowserSourceMaps: false,
|
||||
// Optimize fonts
|
||||
optimizeFonts: true,
|
||||
// Enable React strict mode for better development experience
|
||||
reactStrictMode: true,
|
||||
// Reduce build output size
|
||||
poweredByHeader: false,
|
||||
// Add cache headers to immutable assets
|
||||
async headers() {
|
||||
return [
|
||||
{
|
||||
@ -36,9 +60,31 @@ const nextConfig = {
|
||||
value: "frame-ancestors 'self' https://espace.slm-lab.net https://connect.slm-lab.net"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
source: '/_next/static/:path*',
|
||||
headers: [
|
||||
{
|
||||
key: 'Cache-Control',
|
||||
value: 'public, max-age=31536000, immutable'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
source: '/images/:path*',
|
||||
headers: [
|
||||
{
|
||||
key: 'Cache-Control',
|
||||
value: 'public, max-age=31536000, immutable'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
// Add page redirects if needed
|
||||
async redirects() {
|
||||
return []
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
module.exports = withBundleAnalyzer(nextConfig);
|
||||
227
node_modules/.package-lock.json
generated
vendored
227
node_modules/.package-lock.json
generated
vendored
@ -158,6 +158,16 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@discoveryjs/json-ext": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
|
||||
"integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz",
|
||||
@ -416,6 +426,16 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/bundle-analyzer": {
|
||||
"version": "15.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-15.3.1.tgz",
|
||||
"integrity": "sha512-NqUZrjVruGbdQaPE3OSEXP+ZuULqumeHVTuU9pOX1V0/9BWY9FOck3jgQGFdBtG41nOYuO8+CoHKDQAVIPQJrw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"webpack-bundle-analyzer": "4.10.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/env": {
|
||||
"version": "15.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.1.tgz",
|
||||
@ -508,6 +528,13 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@polka/url": {
|
||||
"version": "1.0.0-next.29",
|
||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
|
||||
"integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@prisma/client": {
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.4.1.tgz",
|
||||
@ -2559,6 +2586,32 @@
|
||||
"node": ">=14.6"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-walk": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
|
||||
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"acorn": "^8.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
|
||||
@ -3071,15 +3124,6 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cookies-next": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cookies-next/-/cookies-next-5.1.0.tgz",
|
||||
@ -3318,6 +3362,13 @@
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/debounce": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
|
||||
"integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||
@ -3515,6 +3566,13 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
@ -3683,6 +3741,19 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
@ -4030,6 +4101,22 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/gzip-size": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
|
||||
"integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"duplexer": "^0.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/has-property-descriptors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||
@ -4108,6 +4195,13 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/html-escaper": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
|
||||
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/html-to-text": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
|
||||
@ -4433,6 +4527,16 @@
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-potential-custom-element-name": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
|
||||
@ -4840,6 +4944,16 @@
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/mrmime": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
|
||||
"integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@ -5138,6 +5252,16 @@
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/opener": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
|
||||
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
|
||||
"dev": true,
|
||||
"license": "(WTFPL OR MIT)",
|
||||
"bin": {
|
||||
"opener": "bin/opener-bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/openid-client": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz",
|
||||
@ -6438,6 +6562,21 @@
|
||||
"is-arrayish": "^0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/sirv": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz",
|
||||
"integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@polka/url": "^1.0.0-next.24",
|
||||
"mrmime": "^2.0.0",
|
||||
"totalist": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/smart-buffer": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||
@ -6850,6 +6989,16 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/totalist": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
|
||||
"integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
|
||||
@ -7176,6 +7325,66 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-bundle-analyzer": {
|
||||
"version": "4.10.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz",
|
||||
"integrity": "sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@discoveryjs/json-ext": "0.5.7",
|
||||
"acorn": "^8.0.4",
|
||||
"acorn-walk": "^8.0.0",
|
||||
"commander": "^7.2.0",
|
||||
"debounce": "^1.2.1",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"gzip-size": "^6.0.0",
|
||||
"html-escaper": "^2.0.2",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"opener": "^1.5.2",
|
||||
"picocolors": "^1.0.0",
|
||||
"sirv": "^2.0.3",
|
||||
"ws": "^7.3.1"
|
||||
},
|
||||
"bin": {
|
||||
"webpack-bundle-analyzer": "lib/bin/analyzer.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-bundle-analyzer/node_modules/commander": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-bundle-analyzer/node_modules/ws": {
|
||||
"version": "7.5.10",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
|
||||
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-encoding": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
|
||||
|
||||
24
node_modules/cookie/LICENSE
generated
vendored
24
node_modules/cookie/LICENSE
generated
vendored
@ -1,24 +0,0 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2012-2014 Roman Shtylman <shtylman@gmail.com>
|
||||
Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
317
node_modules/cookie/README.md
generated
vendored
317
node_modules/cookie/README.md
generated
vendored
@ -1,317 +0,0 @@
|
||||
# cookie
|
||||
|
||||
[![NPM Version][npm-version-image]][npm-url]
|
||||
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||
[![Node.js Version][node-image]][node-url]
|
||||
[![Build Status][ci-image]][ci-url]
|
||||
[![Coverage Status][coveralls-image]][coveralls-url]
|
||||
|
||||
Basic HTTP cookie parser and serializer for HTTP servers.
|
||||
|
||||
## Installation
|
||||
|
||||
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||
|
||||
```sh
|
||||
$ npm install cookie
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var cookie = require('cookie');
|
||||
```
|
||||
|
||||
### cookie.parse(str, options)
|
||||
|
||||
Parse an HTTP `Cookie` header string and returning an object of all cookie name-value pairs.
|
||||
The `str` argument is the string representing a `Cookie` header value and `options` is an
|
||||
optional object containing additional parsing options.
|
||||
|
||||
```js
|
||||
var cookies = cookie.parse('foo=bar; equation=E%3Dmc%5E2');
|
||||
// { foo: 'bar', equation: 'E=mc^2' }
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
`cookie.parse` accepts these properties in the options object.
|
||||
|
||||
##### decode
|
||||
|
||||
Specifies a function that will be used to decode a cookie's value. Since the value of a cookie
|
||||
has a limited character set (and must be a simple string), this function can be used to decode
|
||||
a previously-encoded cookie value into a JavaScript string or other object.
|
||||
|
||||
The default function is the global `decodeURIComponent`, which will decode any URL-encoded
|
||||
sequences into their byte representations.
|
||||
|
||||
**note** if an error is thrown from this function, the original, non-decoded cookie value will
|
||||
be returned as the cookie's value.
|
||||
|
||||
### cookie.serialize(name, value, options)
|
||||
|
||||
Serialize a cookie name-value pair into a `Set-Cookie` header string. The `name` argument is the
|
||||
name for the cookie, the `value` argument is the value to set the cookie to, and the `options`
|
||||
argument is an optional object containing additional serialization options.
|
||||
|
||||
```js
|
||||
var setCookie = cookie.serialize('foo', 'bar');
|
||||
// foo=bar
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
`cookie.serialize` accepts these properties in the options object.
|
||||
|
||||
##### domain
|
||||
|
||||
Specifies the value for the [`Domain` `Set-Cookie` attribute][rfc-6265-5.2.3]. By default, no
|
||||
domain is set, and most clients will consider the cookie to apply to only the current domain.
|
||||
|
||||
##### encode
|
||||
|
||||
Specifies a function that will be used to encode a cookie's value. Since value of a cookie
|
||||
has a limited character set (and must be a simple string), this function can be used to encode
|
||||
a value into a string suited for a cookie's value.
|
||||
|
||||
The default function is the global `encodeURIComponent`, which will encode a JavaScript string
|
||||
into UTF-8 byte sequences and then URL-encode any that fall outside of the cookie range.
|
||||
|
||||
##### expires
|
||||
|
||||
Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute][rfc-6265-5.2.1].
|
||||
By default, no expiration is set, and most clients will consider this a "non-persistent cookie" and
|
||||
will delete it on a condition like exiting a web browser application.
|
||||
|
||||
**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and
|
||||
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
||||
so if both are set, they should point to the same date and time.
|
||||
|
||||
##### httpOnly
|
||||
|
||||
Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute][rfc-6265-5.2.6]. When truthy,
|
||||
the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly` attribute is not set.
|
||||
|
||||
**note** be careful when setting this to `true`, as compliant clients will not allow client-side
|
||||
JavaScript to see the cookie in `document.cookie`.
|
||||
|
||||
##### maxAge
|
||||
|
||||
Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute][rfc-6265-5.2.2].
|
||||
The given number will be converted to an integer by rounding down. By default, no maximum age is set.
|
||||
|
||||
**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and
|
||||
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
||||
so if both are set, they should point to the same date and time.
|
||||
|
||||
##### partitioned
|
||||
|
||||
Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](rfc-cutler-httpbis-partitioned-cookies)
|
||||
attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not. By default, the
|
||||
`Partitioned` attribute is not set.
|
||||
|
||||
**note** This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||
This also means many clients may ignore this attribute until they understand it.
|
||||
|
||||
More information about can be found in [the proposal](https://github.com/privacycg/CHIPS).
|
||||
|
||||
##### path
|
||||
|
||||
Specifies the value for the [`Path` `Set-Cookie` attribute][rfc-6265-5.2.4]. By default, the path
|
||||
is considered the ["default path"][rfc-6265-5.1.4].
|
||||
|
||||
##### priority
|
||||
|
||||
Specifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute][rfc-west-cookie-priority-00-4.1].
|
||||
|
||||
- `'low'` will set the `Priority` attribute to `Low`.
|
||||
- `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
|
||||
- `'high'` will set the `Priority` attribute to `High`.
|
||||
|
||||
More information about the different priority levels can be found in
|
||||
[the specification][rfc-west-cookie-priority-00-4.1].
|
||||
|
||||
**note** This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||
This also means many clients may ignore this attribute until they understand it.
|
||||
|
||||
##### sameSite
|
||||
|
||||
Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][rfc-6265bis-09-5.4.7].
|
||||
|
||||
- `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||
- `false` will not set the `SameSite` attribute.
|
||||
- `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
|
||||
- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
|
||||
- `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||
|
||||
More information about the different enforcement levels can be found in
|
||||
[the specification][rfc-6265bis-09-5.4.7].
|
||||
|
||||
**note** This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||
This also means many clients may ignore this attribute until they understand it.
|
||||
|
||||
##### secure
|
||||
|
||||
Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute][rfc-6265-5.2.5]. When truthy,
|
||||
the `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set.
|
||||
|
||||
**note** be careful when setting this to `true`, as compliant clients will not send the cookie back to
|
||||
the server in the future if the browser does not have an HTTPS connection.
|
||||
|
||||
## Example
|
||||
|
||||
The following example uses this module in conjunction with the Node.js core HTTP server
|
||||
to prompt a user for their name and display it back on future visits.
|
||||
|
||||
```js
|
||||
var cookie = require('cookie');
|
||||
var escapeHtml = require('escape-html');
|
||||
var http = require('http');
|
||||
var url = require('url');
|
||||
|
||||
function onRequest(req, res) {
|
||||
// Parse the query string
|
||||
var query = url.parse(req.url, true, true).query;
|
||||
|
||||
if (query && query.name) {
|
||||
// Set a new cookie with the name
|
||||
res.setHeader('Set-Cookie', cookie.serialize('name', String(query.name), {
|
||||
httpOnly: true,
|
||||
maxAge: 60 * 60 * 24 * 7 // 1 week
|
||||
}));
|
||||
|
||||
// Redirect back after setting cookie
|
||||
res.statusCode = 302;
|
||||
res.setHeader('Location', req.headers.referer || '/');
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the cookies on the request
|
||||
var cookies = cookie.parse(req.headers.cookie || '');
|
||||
|
||||
// Get the visitor name set in the cookie
|
||||
var name = cookies.name;
|
||||
|
||||
res.setHeader('Content-Type', 'text/html; charset=UTF-8');
|
||||
|
||||
if (name) {
|
||||
res.write('<p>Welcome back, <b>' + escapeHtml(name) + '</b>!</p>');
|
||||
} else {
|
||||
res.write('<p>Hello, new visitor!</p>');
|
||||
}
|
||||
|
||||
res.write('<form method="GET">');
|
||||
res.write('<input placeholder="enter your name" name="name"> <input type="submit" value="Set Name">');
|
||||
res.end('</form>');
|
||||
}
|
||||
|
||||
http.createServer(onRequest).listen(3000);
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```sh
|
||||
$ npm test
|
||||
```
|
||||
|
||||
## Benchmark
|
||||
|
||||
```
|
||||
$ npm run bench
|
||||
|
||||
> cookie@0.5.0 bench
|
||||
> node benchmark/index.js
|
||||
|
||||
node@18.18.2
|
||||
acorn@8.10.0
|
||||
ada@2.6.0
|
||||
ares@1.19.1
|
||||
brotli@1.0.9
|
||||
cldr@43.1
|
||||
icu@73.2
|
||||
llhttp@6.0.11
|
||||
modules@108
|
||||
napi@9
|
||||
nghttp2@1.57.0
|
||||
nghttp3@0.7.0
|
||||
ngtcp2@0.8.1
|
||||
openssl@3.0.10+quic
|
||||
simdutf@3.2.14
|
||||
tz@2023c
|
||||
undici@5.26.3
|
||||
unicode@15.0
|
||||
uv@1.44.2
|
||||
uvwasi@0.0.18
|
||||
v8@10.2.154.26-node.26
|
||||
zlib@1.2.13.1-motley
|
||||
|
||||
> node benchmark/parse-top.js
|
||||
|
||||
cookie.parse - top sites
|
||||
|
||||
14 tests completed.
|
||||
|
||||
parse accounts.google.com x 2,588,913 ops/sec ±0.74% (186 runs sampled)
|
||||
parse apple.com x 2,370,002 ops/sec ±0.69% (186 runs sampled)
|
||||
parse cloudflare.com x 2,213,102 ops/sec ±0.88% (188 runs sampled)
|
||||
parse docs.google.com x 2,194,157 ops/sec ±1.03% (184 runs sampled)
|
||||
parse drive.google.com x 2,265,084 ops/sec ±0.79% (187 runs sampled)
|
||||
parse en.wikipedia.org x 457,099 ops/sec ±0.81% (186 runs sampled)
|
||||
parse linkedin.com x 504,407 ops/sec ±0.89% (186 runs sampled)
|
||||
parse maps.google.com x 1,230,959 ops/sec ±0.98% (186 runs sampled)
|
||||
parse microsoft.com x 926,294 ops/sec ±0.88% (184 runs sampled)
|
||||
parse play.google.com x 2,311,338 ops/sec ±0.83% (185 runs sampled)
|
||||
parse support.google.com x 1,508,850 ops/sec ±0.86% (186 runs sampled)
|
||||
parse www.google.com x 1,022,582 ops/sec ±1.32% (182 runs sampled)
|
||||
parse youtu.be x 332,136 ops/sec ±1.02% (185 runs sampled)
|
||||
parse youtube.com x 323,833 ops/sec ±0.77% (183 runs sampled)
|
||||
|
||||
> node benchmark/parse.js
|
||||
|
||||
cookie.parse - generic
|
||||
|
||||
6 tests completed.
|
||||
|
||||
simple x 3,214,032 ops/sec ±1.61% (183 runs sampled)
|
||||
decode x 587,237 ops/sec ±1.16% (187 runs sampled)
|
||||
unquote x 2,954,618 ops/sec ±1.35% (183 runs sampled)
|
||||
duplicates x 857,008 ops/sec ±0.89% (187 runs sampled)
|
||||
10 cookies x 292,133 ops/sec ±0.89% (187 runs sampled)
|
||||
100 cookies x 22,610 ops/sec ±0.68% (187 runs sampled)
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [RFC 6265: HTTP State Management Mechanism][rfc-6265]
|
||||
- [Same-site Cookies][rfc-6265bis-09-5.4.7]
|
||||
|
||||
[rfc-cutler-httpbis-partitioned-cookies]: https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/
|
||||
[rfc-west-cookie-priority-00-4.1]: https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1
|
||||
[rfc-6265bis-09-5.4.7]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7
|
||||
[rfc-6265]: https://tools.ietf.org/html/rfc6265
|
||||
[rfc-6265-5.1.4]: https://tools.ietf.org/html/rfc6265#section-5.1.4
|
||||
[rfc-6265-5.2.1]: https://tools.ietf.org/html/rfc6265#section-5.2.1
|
||||
[rfc-6265-5.2.2]: https://tools.ietf.org/html/rfc6265#section-5.2.2
|
||||
[rfc-6265-5.2.3]: https://tools.ietf.org/html/rfc6265#section-5.2.3
|
||||
[rfc-6265-5.2.4]: https://tools.ietf.org/html/rfc6265#section-5.2.4
|
||||
[rfc-6265-5.2.5]: https://tools.ietf.org/html/rfc6265#section-5.2.5
|
||||
[rfc-6265-5.2.6]: https://tools.ietf.org/html/rfc6265#section-5.2.6
|
||||
[rfc-6265-5.3]: https://tools.ietf.org/html/rfc6265#section-5.3
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[ci-image]: https://badgen.net/github/checks/jshttp/cookie/master?label=ci
|
||||
[ci-url]: https://github.com/jshttp/cookie/actions/workflows/ci.yml
|
||||
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/cookie/master
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/cookie?branch=master
|
||||
[node-image]: https://badgen.net/npm/node/cookie
|
||||
[node-url]: https://nodejs.org/en/download
|
||||
[npm-downloads-image]: https://badgen.net/npm/dm/cookie
|
||||
[npm-url]: https://npmjs.org/package/cookie
|
||||
[npm-version-image]: https://badgen.net/npm/v/cookie
|
||||
25
node_modules/cookie/SECURITY.md
generated
vendored
25
node_modules/cookie/SECURITY.md
generated
vendored
@ -1,25 +0,0 @@
|
||||
# Security Policies and Procedures
|
||||
|
||||
## Reporting a Bug
|
||||
|
||||
The `cookie` team and community take all security bugs seriously. Thank
|
||||
you for improving the security of the project. We appreciate your efforts and
|
||||
responsible disclosure and will make every effort to acknowledge your
|
||||
contributions.
|
||||
|
||||
Report security bugs by emailing the current owner(s) of `cookie`. This
|
||||
information can be found in the npm registry using the command
|
||||
`npm owner ls cookie`.
|
||||
If unsure or unable to get the information from the above, open an issue
|
||||
in the [project issue tracker](https://github.com/jshttp/cookie/issues)
|
||||
asking for the current contact information.
|
||||
|
||||
To ensure the timely response to your report, please ensure that the entirety
|
||||
of the report is contained within the email body and not solely behind a web
|
||||
link or an attachment.
|
||||
|
||||
At least one owner will acknowledge your email within 48 hours, and will send a
|
||||
more detailed response within 48 hours indicating the next steps in handling
|
||||
your report. After the initial reply to your report, the owners will
|
||||
endeavor to keep you informed of the progress towards a fix and full
|
||||
announcement, and may ask for additional information or guidance.
|
||||
274
node_modules/cookie/index.js
generated
vendored
274
node_modules/cookie/index.js
generated
vendored
@ -1,274 +0,0 @@
|
||||
/*!
|
||||
* cookie
|
||||
* Copyright(c) 2012-2014 Roman Shtylman
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
exports.parse = parse;
|
||||
exports.serialize = serialize;
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var __toString = Object.prototype.toString
|
||||
|
||||
/**
|
||||
* RegExp to match field-content in RFC 7230 sec 3.2
|
||||
*
|
||||
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||
* field-vchar = VCHAR / obs-text
|
||||
* obs-text = %x80-FF
|
||||
*/
|
||||
|
||||
var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
|
||||
|
||||
/**
|
||||
* Parse a cookie header.
|
||||
*
|
||||
* Parse the given cookie header string into an object
|
||||
* The object has the various cookies as keys(names) => values
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {object} [options]
|
||||
* @return {object}
|
||||
* @public
|
||||
*/
|
||||
|
||||
function parse(str, options) {
|
||||
if (typeof str !== 'string') {
|
||||
throw new TypeError('argument str must be a string');
|
||||
}
|
||||
|
||||
var obj = {}
|
||||
var opt = options || {};
|
||||
var dec = opt.decode || decode;
|
||||
|
||||
var index = 0
|
||||
while (index < str.length) {
|
||||
var eqIdx = str.indexOf('=', index)
|
||||
|
||||
// no more cookie pairs
|
||||
if (eqIdx === -1) {
|
||||
break
|
||||
}
|
||||
|
||||
var endIdx = str.indexOf(';', index)
|
||||
|
||||
if (endIdx === -1) {
|
||||
endIdx = str.length
|
||||
} else if (endIdx < eqIdx) {
|
||||
// backtrack on prior semicolon
|
||||
index = str.lastIndexOf(';', eqIdx - 1) + 1
|
||||
continue
|
||||
}
|
||||
|
||||
var key = str.slice(index, eqIdx).trim()
|
||||
|
||||
// only assign once
|
||||
if (undefined === obj[key]) {
|
||||
var val = str.slice(eqIdx + 1, endIdx).trim()
|
||||
|
||||
// quoted values
|
||||
if (val.charCodeAt(0) === 0x22) {
|
||||
val = val.slice(1, -1)
|
||||
}
|
||||
|
||||
obj[key] = tryDecode(val, dec);
|
||||
}
|
||||
|
||||
index = endIdx + 1
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize data into a cookie header.
|
||||
*
|
||||
* Serialize the a name value pair into a cookie string suitable for
|
||||
* http headers. An optional options object specified cookie parameters.
|
||||
*
|
||||
* serialize('foo', 'bar', { httpOnly: true })
|
||||
* => "foo=bar; httpOnly"
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {string} val
|
||||
* @param {object} [options]
|
||||
* @return {string}
|
||||
* @public
|
||||
*/
|
||||
|
||||
function serialize(name, val, options) {
|
||||
var opt = options || {};
|
||||
var enc = opt.encode || encode;
|
||||
|
||||
if (typeof enc !== 'function') {
|
||||
throw new TypeError('option encode is invalid');
|
||||
}
|
||||
|
||||
if (!fieldContentRegExp.test(name)) {
|
||||
throw new TypeError('argument name is invalid');
|
||||
}
|
||||
|
||||
var value = enc(val);
|
||||
|
||||
if (value && !fieldContentRegExp.test(value)) {
|
||||
throw new TypeError('argument val is invalid');
|
||||
}
|
||||
|
||||
var str = name + '=' + value;
|
||||
|
||||
if (null != opt.maxAge) {
|
||||
var maxAge = opt.maxAge - 0;
|
||||
|
||||
if (isNaN(maxAge) || !isFinite(maxAge)) {
|
||||
throw new TypeError('option maxAge is invalid')
|
||||
}
|
||||
|
||||
str += '; Max-Age=' + Math.floor(maxAge);
|
||||
}
|
||||
|
||||
if (opt.domain) {
|
||||
if (!fieldContentRegExp.test(opt.domain)) {
|
||||
throw new TypeError('option domain is invalid');
|
||||
}
|
||||
|
||||
str += '; Domain=' + opt.domain;
|
||||
}
|
||||
|
||||
if (opt.path) {
|
||||
if (!fieldContentRegExp.test(opt.path)) {
|
||||
throw new TypeError('option path is invalid');
|
||||
}
|
||||
|
||||
str += '; Path=' + opt.path;
|
||||
}
|
||||
|
||||
if (opt.expires) {
|
||||
var expires = opt.expires
|
||||
|
||||
if (!isDate(expires) || isNaN(expires.valueOf())) {
|
||||
throw new TypeError('option expires is invalid');
|
||||
}
|
||||
|
||||
str += '; Expires=' + expires.toUTCString()
|
||||
}
|
||||
|
||||
if (opt.httpOnly) {
|
||||
str += '; HttpOnly';
|
||||
}
|
||||
|
||||
if (opt.secure) {
|
||||
str += '; Secure';
|
||||
}
|
||||
|
||||
if (opt.partitioned) {
|
||||
str += '; Partitioned'
|
||||
}
|
||||
|
||||
if (opt.priority) {
|
||||
var priority = typeof opt.priority === 'string'
|
||||
? opt.priority.toLowerCase()
|
||||
: opt.priority
|
||||
|
||||
switch (priority) {
|
||||
case 'low':
|
||||
str += '; Priority=Low'
|
||||
break
|
||||
case 'medium':
|
||||
str += '; Priority=Medium'
|
||||
break
|
||||
case 'high':
|
||||
str += '; Priority=High'
|
||||
break
|
||||
default:
|
||||
throw new TypeError('option priority is invalid')
|
||||
}
|
||||
}
|
||||
|
||||
if (opt.sameSite) {
|
||||
var sameSite = typeof opt.sameSite === 'string'
|
||||
? opt.sameSite.toLowerCase() : opt.sameSite;
|
||||
|
||||
switch (sameSite) {
|
||||
case true:
|
||||
str += '; SameSite=Strict';
|
||||
break;
|
||||
case 'lax':
|
||||
str += '; SameSite=Lax';
|
||||
break;
|
||||
case 'strict':
|
||||
str += '; SameSite=Strict';
|
||||
break;
|
||||
case 'none':
|
||||
str += '; SameSite=None';
|
||||
break;
|
||||
default:
|
||||
throw new TypeError('option sameSite is invalid');
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* URL-decode string value. Optimized to skip native call when no %.
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
function decode (str) {
|
||||
return str.indexOf('%') !== -1
|
||||
? decodeURIComponent(str)
|
||||
: str
|
||||
}
|
||||
|
||||
/**
|
||||
* URL-encode value.
|
||||
*
|
||||
* @param {string} val
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
function encode (val) {
|
||||
return encodeURIComponent(val)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if value is a Date.
|
||||
*
|
||||
* @param {*} val
|
||||
* @private
|
||||
*/
|
||||
|
||||
function isDate (val) {
|
||||
return __toString.call(val) === '[object Date]' ||
|
||||
val instanceof Date
|
||||
}
|
||||
|
||||
/**
|
||||
* Try decoding a string using a decoding function.
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {function} decode
|
||||
* @private
|
||||
*/
|
||||
|
||||
function tryDecode(str, decode) {
|
||||
try {
|
||||
return decode(str);
|
||||
} catch (e) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
44
node_modules/cookie/package.json
generated
vendored
44
node_modules/cookie/package.json
generated
vendored
@ -1,44 +0,0 @@
|
||||
{
|
||||
"name": "cookie",
|
||||
"description": "HTTP server cookie parsing and serialization",
|
||||
"version": "0.6.0",
|
||||
"author": "Roman Shtylman <shtylman@gmail.com>",
|
||||
"contributors": [
|
||||
"Douglas Christopher Wilson <doug@somethingdoug.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"cookie",
|
||||
"cookies"
|
||||
],
|
||||
"repository": "jshttp/cookie",
|
||||
"devDependencies": {
|
||||
"beautify-benchmark": "0.2.4",
|
||||
"benchmark": "2.1.4",
|
||||
"eslint": "8.53.0",
|
||||
"eslint-plugin-markdown": "3.0.1",
|
||||
"mocha": "10.2.0",
|
||||
"nyc": "15.1.0",
|
||||
"safe-buffer": "5.2.1",
|
||||
"top-sites": "1.1.194"
|
||||
},
|
||||
"files": [
|
||||
"HISTORY.md",
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"SECURITY.md",
|
||||
"index.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
},
|
||||
"scripts": {
|
||||
"bench": "node benchmark/index.js",
|
||||
"lint": "eslint .",
|
||||
"test": "mocha --reporter spec --bail --check-leaks test/",
|
||||
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
|
||||
"test-cov": "nyc --reporter=html --reporter=text npm test",
|
||||
"update-bench": "node scripts/update-benchmark.js",
|
||||
"version": "node scripts/version-history.js && git add HISTORY.md"
|
||||
}
|
||||
}
|
||||
229
package-lock.json
generated
229
package-lock.json
generated
@ -53,7 +53,6 @@
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "1.0.4",
|
||||
"cookie": "^0.6.0",
|
||||
"cookies-next": "^5.1.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"date-fns": "^3.6.0",
|
||||
@ -95,6 +94,7 @@
|
||||
"webdav": "^5.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "^15.3.1",
|
||||
"@types/cookie": "^0.6.0",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/imapflow": "^1.0.20",
|
||||
@ -267,6 +267,16 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@discoveryjs/json-ext": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
|
||||
"integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/runtime": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz",
|
||||
@ -1282,6 +1292,16 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/bundle-analyzer": {
|
||||
"version": "15.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-15.3.1.tgz",
|
||||
"integrity": "sha512-NqUZrjVruGbdQaPE3OSEXP+ZuULqumeHVTuU9pOX1V0/9BWY9FOck3jgQGFdBtG41nOYuO8+CoHKDQAVIPQJrw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"webpack-bundle-analyzer": "4.10.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/env": {
|
||||
"version": "15.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.1.tgz",
|
||||
@ -1486,6 +1506,13 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@polka/url": {
|
||||
"version": "1.0.0-next.29",
|
||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
|
||||
"integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@prisma/client": {
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.4.1.tgz",
|
||||
@ -3537,6 +3564,32 @@
|
||||
"node": ">=14.6"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-walk": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
|
||||
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"acorn": "^8.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
|
||||
@ -4049,15 +4102,6 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cookies-next": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cookies-next/-/cookies-next-5.1.0.tgz",
|
||||
@ -4296,6 +4340,13 @@
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/debounce": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
|
||||
"integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||
@ -4493,6 +4544,13 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
@ -4661,6 +4719,19 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
@ -5008,6 +5079,22 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/gzip-size": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
|
||||
"integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"duplexer": "^0.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/has-property-descriptors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||
@ -5086,6 +5173,13 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/html-escaper": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
|
||||
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/html-to-text": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
|
||||
@ -5411,6 +5505,16 @@
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-potential-custom-element-name": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
|
||||
@ -5818,6 +5922,16 @@
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/mrmime": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
|
||||
"integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@ -6116,6 +6230,16 @@
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/opener": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
|
||||
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
|
||||
"dev": true,
|
||||
"license": "(WTFPL OR MIT)",
|
||||
"bin": {
|
||||
"opener": "bin/opener-bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/openid-client": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz",
|
||||
@ -7416,6 +7540,21 @@
|
||||
"is-arrayish": "^0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/sirv": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz",
|
||||
"integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@polka/url": "^1.0.0-next.24",
|
||||
"mrmime": "^2.0.0",
|
||||
"totalist": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/smart-buffer": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||
@ -7828,6 +7967,16 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/totalist": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
|
||||
"integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
|
||||
@ -8154,6 +8303,66 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-bundle-analyzer": {
|
||||
"version": "4.10.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz",
|
||||
"integrity": "sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@discoveryjs/json-ext": "0.5.7",
|
||||
"acorn": "^8.0.4",
|
||||
"acorn-walk": "^8.0.0",
|
||||
"commander": "^7.2.0",
|
||||
"debounce": "^1.2.1",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"gzip-size": "^6.0.0",
|
||||
"html-escaper": "^2.0.2",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"opener": "^1.5.2",
|
||||
"picocolors": "^1.0.0",
|
||||
"sirv": "^2.0.3",
|
||||
"ws": "^7.3.1"
|
||||
},
|
||||
"bin": {
|
||||
"webpack-bundle-analyzer": "lib/bin/analyzer.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-bundle-analyzer/node_modules/commander": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-bundle-analyzer/node_modules/ws": {
|
||||
"version": "7.5.10",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
|
||||
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-encoding": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
|
||||
|
||||
@ -95,6 +95,7 @@
|
||||
"webdav": "^5.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "^15.3.1",
|
||||
"@types/cookie": "^0.6.0",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/imapflow": "^1.0.20",
|
||||
|
||||
117
yarn.lock
117
yarn.lock
@ -60,6 +60,11 @@
|
||||
resolved "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz"
|
||||
integrity sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==
|
||||
|
||||
"@discoveryjs/json-ext@0.5.7":
|
||||
version "0.5.7"
|
||||
resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz"
|
||||
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
|
||||
|
||||
"@esbuild/darwin-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz"
|
||||
@ -217,6 +222,13 @@
|
||||
"@jridgewell/resolve-uri" "^3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||
|
||||
"@next/bundle-analyzer@^15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-15.3.1.tgz"
|
||||
integrity sha512-NqUZrjVruGbdQaPE3OSEXP+ZuULqumeHVTuU9pOX1V0/9BWY9FOck3jgQGFdBtG41nOYuO8+CoHKDQAVIPQJrw==
|
||||
dependencies:
|
||||
webpack-bundle-analyzer "4.10.1"
|
||||
|
||||
"@next/env@15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.npmjs.org/@next/env/-/env-15.3.1.tgz"
|
||||
@ -274,6 +286,11 @@
|
||||
resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@polka/url@^1.0.0-next.24":
|
||||
version "1.0.0-next.29"
|
||||
resolved "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz"
|
||||
integrity sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==
|
||||
|
||||
"@prisma/client@^6.4.1":
|
||||
version "6.4.1"
|
||||
resolved "https://registry.npmjs.org/@prisma/client/-/client-6.4.1.tgz"
|
||||
@ -1213,6 +1230,18 @@
|
||||
resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.8.tgz"
|
||||
integrity sha512-p96FSY54r+WJ50FIOsCOjyj/wavs8921hG5+kVMmZgKcvIKxMXHTrjNJvRgWa/zuX3B6t2lijLNFaOyuxUH+2A==
|
||||
|
||||
acorn-walk@^8.0.0:
|
||||
version "8.3.4"
|
||||
resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz"
|
||||
integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==
|
||||
dependencies:
|
||||
acorn "^8.11.0"
|
||||
|
||||
acorn@^8.0.4, acorn@^8.11.0:
|
||||
version "8.14.1"
|
||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz"
|
||||
integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
|
||||
|
||||
agent-base@^7.1.0, agent-base@^7.1.2:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz"
|
||||
@ -1500,10 +1529,10 @@ commander@^4.0.0:
|
||||
resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz"
|
||||
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
|
||||
|
||||
cookie@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz"
|
||||
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
|
||||
commander@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz"
|
||||
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
|
||||
|
||||
cookie@^0.7.0:
|
||||
version "0.7.2"
|
||||
@ -1663,6 +1692,11 @@ date-fns@^4.1.0:
|
||||
resolved "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz"
|
||||
integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==
|
||||
|
||||
debounce@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz"
|
||||
integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==
|
||||
|
||||
debug@^4.3.4, debug@4:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz"
|
||||
@ -1783,6 +1817,11 @@ dunder-proto@^1.0.1:
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.2.0"
|
||||
|
||||
duplexer@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz"
|
||||
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
|
||||
|
||||
eastasianwidth@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz"
|
||||
@ -1906,6 +1945,11 @@ escalade@^3.2.0:
|
||||
resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz"
|
||||
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
|
||||
|
||||
escape-string-regexp@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
|
||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||
|
||||
eventemitter3@^4.0.1:
|
||||
version "4.0.7"
|
||||
resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz"
|
||||
@ -2102,6 +2146,13 @@ gopd@^1.0.1, gopd@^1.2.0:
|
||||
resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz"
|
||||
integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
|
||||
|
||||
gzip-size@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz"
|
||||
integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==
|
||||
dependencies:
|
||||
duplexer "^0.1.2"
|
||||
|
||||
has-property-descriptors@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz"
|
||||
@ -2145,6 +2196,11 @@ html-encoding-sniffer@^4.0.0:
|
||||
dependencies:
|
||||
whatwg-encoding "^3.1.1"
|
||||
|
||||
html-escaper@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz"
|
||||
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
|
||||
|
||||
html-to-text@9.0.5:
|
||||
version "9.0.5"
|
||||
resolved "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz"
|
||||
@ -2324,6 +2380,11 @@ is-number@^7.0.0:
|
||||
resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
is-plain-object@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz"
|
||||
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
|
||||
|
||||
is-potential-custom-element-name@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz"
|
||||
@ -2627,6 +2688,11 @@ minimatch@^9.0.4, minimatch@^9.0.5:
|
||||
resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz"
|
||||
integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
|
||||
|
||||
mrmime@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz"
|
||||
integrity sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==
|
||||
|
||||
ms@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
|
||||
@ -2785,6 +2851,11 @@ on-exit-leak-free@^2.1.0:
|
||||
resolved "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz"
|
||||
integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==
|
||||
|
||||
opener@^1.5.2:
|
||||
version "1.5.2"
|
||||
resolved "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz"
|
||||
integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
|
||||
|
||||
openid-client@^5.4.0:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz"
|
||||
@ -3523,6 +3594,15 @@ simple-swizzle@^0.2.2:
|
||||
dependencies:
|
||||
is-arrayish "^0.3.1"
|
||||
|
||||
sirv@^2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz"
|
||||
integrity sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==
|
||||
dependencies:
|
||||
"@polka/url" "^1.0.0-next.24"
|
||||
mrmime "^2.0.0"
|
||||
totalist "^3.0.0"
|
||||
|
||||
smart-buffer@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz"
|
||||
@ -3769,6 +3849,11 @@ to-regex-range@^5.0.1:
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
totalist@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz"
|
||||
integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==
|
||||
|
||||
tough-cookie@^5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz"
|
||||
@ -3966,6 +4051,25 @@ webidl-conversions@^7.0.0:
|
||||
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz"
|
||||
integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==
|
||||
|
||||
webpack-bundle-analyzer@4.10.1:
|
||||
version "4.10.1"
|
||||
resolved "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz"
|
||||
integrity sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==
|
||||
dependencies:
|
||||
"@discoveryjs/json-ext" "0.5.7"
|
||||
acorn "^8.0.4"
|
||||
acorn-walk "^8.0.0"
|
||||
commander "^7.2.0"
|
||||
debounce "^1.2.1"
|
||||
escape-string-regexp "^4.0.0"
|
||||
gzip-size "^6.0.0"
|
||||
html-escaper "^2.0.2"
|
||||
is-plain-object "^5.0.0"
|
||||
opener "^1.5.2"
|
||||
picocolors "^1.0.0"
|
||||
sirv "^2.0.3"
|
||||
ws "^7.3.1"
|
||||
|
||||
whatwg-encoding@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz"
|
||||
@ -4024,6 +4128,11 @@ wrap-ansi@^8.1.0:
|
||||
string-width "^5.0.1"
|
||||
strip-ansi "^7.0.1"
|
||||
|
||||
ws@^7.3.1:
|
||||
version "7.5.10"
|
||||
resolved "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz"
|
||||
integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==
|
||||
|
||||
ws@^8.18.0:
|
||||
version "8.18.1"
|
||||
resolved "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user