Compare commits

..

No commits in common. "7d0bb445689054648ee3d3358b64c33ba45e934b" and "24488494ae2304dfa073fbabc73b771a155e8b6e" have entirely different histories.

37 changed files with 717 additions and 1205 deletions

@ -63,6 +63,7 @@ const nextConfig = {
ignoreBuildErrors: true,
},
experimental: {
missingSuspenseWithCSRBailout: false,
},
};

@ -2,7 +2,6 @@
"name": "mhsf",
"version": "1.3.0",
"private": true,
"type": "module",
"packageManager": "yarn@1.22.22",
"scripts": {
"dev": "next dev",
@ -44,8 +43,8 @@
"@trpc/react-query": "^11.0.0",
"@trpc/server": "^11.0.0",
"@types/lodash": "^4.17.16",
"@types/react": "19.0.10",
"@types/react-dom": "19.0.4",
"@types/react": "^19.0.8",
"@types/react-dom": "^19.0.3",
"@types/request-ip": "^0.0.41",
"@unocss/eslint-plugin": "^0.61.5",
"@unocss/postcss": "^0.61.5",
@ -72,7 +71,7 @@
"monaco-editor": "^0.52.2",
"mongodb": "^6.8.0",
"motion": "^12.7.4",
"next": "^15.3.1",
"next": "15.2.0",
"next-contentlayer": "^0.3.4",
"next-css-obfuscator": "^2.2.16",
"next-sitemap": "^4.2.3",
@ -82,8 +81,8 @@
"nuqs": "^2.4.1",
"postcss-obfuscator": "^1.6.1",
"prettier": "^3.3.1",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-fade-in": "^2.0.1",
"react-fast-marquee": "^1.6.5",
"react-hot-toast": "^2.4.1",
@ -110,18 +109,18 @@
"@clerk/themes": "^2.1.19",
"@hookform/resolvers": "^3.9.0",
"@radix-ui/react-checkbox": "^1.1.1",
"@radix-ui/react-context-menu": "^2.2.6",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-context-menu": "^2.1.5",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-radio-group": "^1.2.0",
"@radix-ui/react-scroll-area": "^1.1.0",
"@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slot": "^1.2.0",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-tooltip": "^1.1.8",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.3",
"@tailwindcss/postcss": "^4.0.7",
"@tailwindcss/typography": "^0.5.13",
"@types/canvas-confetti": "^1.6.4",
@ -136,12 +135,12 @@
"@vercel/analytics": "^1.3.1",
"@vercel/speed-insights": "^1.0.12",
"canvas-confetti": "^1.9.3",
"class-variance-authority": "^0.7.1",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"eslint": "^8",
"eslint-config-next": "15.2.0",
"framer-motion": "^12.7.4",
"framer-motion": "^11.3.8",
"geist": "^1.3.0",
"mangle-css-class-webpack-plugin": "^5.1.0",
"postcss": "^8",
@ -150,12 +149,12 @@
"react-infinite-scroll-component": "^6.1.0",
"react-markdown": "^9.0.1",
"react-resizable-panels": "^2.0.23",
"recharts": "^2.15.1",
"recharts": "^2.12.7",
"shiki": "^1.23.0",
"tailwindcss": "^4.0.7",
"tailwindcss": "^3.4.1",
"typescript": "^5",
"vaul": "^1.1.2",
"zod": "^3.24.2"
"vaul": "^0.9.1",
"zod": "^3.23.8"
},
"resolutions": {
"@types/react": "19.0.10",

@ -0,0 +1,148 @@
/*
* MHSF, Minehut Server List
* All external content is rather licensed under the ECA Agreement
* located here: https://mhsf.app/docs/legal/external-content-agreement
*
* All code under MHSF is licensed under the MIT License
* by open source contributors
*
* Copyright (c) 2025 dvelo
*
* 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.
*/
"use client";
import "../../globals.css";
import { useSearchParams } from "next/navigation";
import { Placeholder } from "@/components/ui/placeholder";
import { Command, X } from "lucide-react";
import { IsScript } from "@/components/util/is-script";
import { Button } from "@/components/ui/button";
import Link from "next/link";
import { NavBar } from "@/components/feat/navbar/navbar";
import { TooltipProvider } from "@/components/ui/tooltip";
import { ThemeProvider } from "@/components/util/theme-provider";
import { FontBoundary } from "@/components/util/font-boundary";
import { ClerkProvider } from "@/components/util/clerk-provider";
import { Toaster } from "sonner";
import { Footer } from "@/components/feat/footer/footer";
import { NuqsAdapter } from "nuqs/adapters/next/app";
import { IframeProtector } from "@/components/util/iframe-protector";
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupContent,
SidebarHeader,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
} from "@/components/ui/sidebar";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const searchParams = useSearchParams();
const search = searchParams?.get("theme") || "light";
return (
<html lang="en">
<noscript>
<main className="flex justify-center items-center text-center min-h-screen h-max">
<Placeholder
icon={<X />}
title="JavaScript is required for MHSF"
description="MHSF cannot grab servers or do other external requests without JavaScript."
>
<Link href="https://www.enable-javascript.com/">
<Button>Here's how</Button>
</Link>
</Placeholder>
</main>
</noscript>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<ClerkProvider>
<IsScript>
<NuqsAdapter>
<FontBoundary>
<TooltipProvider>
<SidebarProvider>
<Sidebar variant="inset">
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg" asChild>
<a href="#">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<Command className="size-4" />
</div>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-semibold">
Acme Inc
</span>
<span className="truncate text-xs">
Enterprise
</span>
</div>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild size="sm">
<a href="#">
<span>a</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
<SidebarInset>
<Toaster richColors position="bottom-center" />
<div className="overflow-x-hidden">{children}</div>
</SidebarInset>
</SidebarProvider>
</TooltipProvider>
</FontBoundary>
</NuqsAdapter>
</IsScript>
</ClerkProvider>
</ThemeProvider>
</html>
);
}

@ -27,17 +27,7 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
"use client";
import { NotFoundComponent } from "@/components/util/not-found";
import type { Metadata } from "next";
export const metadata: Metadata = {
applicationName: "MHSF",
title: "Page not found · MHSF",
description: "Couldn't find the page that was requested.",
};
export default function NotFoundPage() {
return <NotFoundComponent />;
export default function Dashboard() {
return <>Hello world</>
}

@ -46,7 +46,8 @@ export default function RootLayout({
const search = searchParams?.get("theme") || "light";
return (
<>
<html lang="en">
<body className={inter.className}>
<ThemeProvider
attribute="class"
disableTransitionOnChange
@ -54,6 +55,7 @@ export default function RootLayout({
>
<TooltipProvider>{children}</TooltipProvider>
</ThemeProvider>
</>
</body>
</html>
);
}

@ -28,8 +28,14 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
"use client";
import "../globals.css";
import { useSearchParams } from "next/navigation";
import { Placeholder } from "@/components/ui/placeholder";
import { X } from "lucide-react";
import { IsScript } from "@/components/util/is-script";
import { Button } from "@/components/ui/button";
import Link from "next/link";
import { NavBar } from "@/components/feat/navbar/navbar";
import { TooltipProvider } from "@/components/ui/tooltip";
import { ThemeProvider } from "@/components/util/theme-provider";
@ -44,9 +50,24 @@ export default function RootLayout({
}: {
children: React.ReactNode;
}) {
const searchParams = useSearchParams();
const search = searchParams?.get("theme") || "light";
return (
<>
<html lang="en">
<noscript>
<main className="flex justify-center items-center text-center min-h-screen h-max">
<Placeholder
icon={<X />}
title="JavaScript is required for MHSF"
description="MHSF cannot grab servers or do other external requests without JavaScript."
>
<Link href="https://www.enable-javascript.com/">
<Button>Here's how</Button>
</Link>
</Placeholder>
</main>
</noscript>
<ThemeProvider
attribute="class"
defaultTheme="system"
@ -70,6 +91,6 @@ export default function RootLayout({
</IsScript>
</ClerkProvider>
</ThemeProvider>
</>
</html>
);
}

@ -56,7 +56,20 @@ export default function RootLayout({
const search = searchParams?.get("theme") || "light";
return (
<>
<html lang="en">
<noscript>
<main className="flex justify-center items-center text-center min-h-screen h-max">
<Placeholder
icon={<X />}
title="JavaScript is required for MHSF"
description="MHSF cannot grab servers or do other external requests without JavaScript."
>
<Link href="https://www.enable-javascript.com/">
<Button>Here's how</Button>
</Link>
</Placeholder>
</main>
</noscript>
<ThemeProvider
attribute="class"
defaultTheme="system"
@ -80,6 +93,6 @@ export default function RootLayout({
</IsScript>
</ClerkProvider>
</ThemeProvider>
</>
</html>
);
}

@ -134,7 +134,6 @@ export default function ModificationPage({
activatedModifications: modificationArray
}
});
communicator.send("rerender-servers", {});
}}>
{modObj?.active ? "Disable" : "Enable"}
</Button>
@ -166,7 +165,6 @@ export default function ModificationPage({
});
toast.success(`Deleted in ${Date.now() - time}ms`);
router.push(backRoute);
communicator.send("rerender-servers", {});
}}
>
<Trash size={16} /> Delete

@ -32,7 +32,6 @@
@plugin 'tailwindcss-animate';
@config '../../tailwind-hero.config.ts';
@plugin "@tailwindcss/typography";
@custom-variant dark (&:is(.dark *));
@ -79,10 +78,8 @@
border-color: hsl(214.3 31.8% 91.4%);
}
--sidebar: hsl(0 0% 98%);
--sidebar: hsl(0 0% 98%)
}
.dark {
--border: 216 34% 17%;
--background: 0 0% 3.9%;
@ -407,9 +404,6 @@ body {
padding-left: 20px;
color: var(--mauve-11);
}
.slot[data-swapy-highlighted] {
@apply bg-muted rounded transition-all
}
.icon-minecraft,
.icon-minecraft-sm {
display: inline-block;

@ -28,12 +28,10 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
import { Placeholder } from "@/components/ui/placeholder";
"use client";
import "./globals.css";
import { useSearchParams } from "next/navigation";
import { Inter } from "next/font/google";
import { X } from "lucide-react";
import { Link } from "@/components/util/link";
import { Button } from "@/components/ui/button";
const inter = Inter({ subsets: ["latin"] });
@ -42,22 +40,13 @@ export default function RootLayout({
}: {
children: React.ReactNode;
}) {
const searchParams = useSearchParams();
const search = searchParams?.get("theme") || "light";
return (
<html lang="en">
<body className={inter.className}>
<noscript>
<main className="flex justify-center items-center text-center min-h-screen h-max">
<Placeholder
icon={<X />}
title="JavaScript is required for MHSF"
description="MHSF cannot grab servers or do other external requests without JavaScript."
>
<Link href="https://www.enable-javascript.com/" noExtraIcons>
<Button>Here's how</Button>
</Link>
</Placeholder>
</main>
</noscript>
<noscript>{children}</noscript>
{children}
</body>
</html>

@ -0,0 +1,69 @@
import { ComponentPropsWithoutRef, ReactNode } from "react";
import { cn } from "@/lib/utils";
interface BentoGridProps extends ComponentPropsWithoutRef<"div"> {
children: ReactNode;
className?: string;
}
interface BentoCardProps extends ComponentPropsWithoutRef<"div"> {
name: string;
className: string;
background: ReactNode;
Icon: React.ElementType;
description: string;
href: string;
cta: string;
}
const BentoGrid = ({ children, className, ...props }: BentoGridProps) => {
return (
<div
className={cn(
"grid w-full auto-rows-[22rem] grid-cols-3 gap-4",
className
)}
{...props}
>
{children}
</div>
);
};
const BentoCard = ({
name,
className,
background,
Icon,
description,
href,
cta,
...props
}: BentoCardProps) => (
<div
key={name}
className={cn(
"group relative col-span-3 flex flex-col justify-between overflow-hidden rounded-xl",
// light styles
"bg-background [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)]",
// dark styles
"transform-gpu dark:bg-background dark:[border:1px_solid_rgba(255,255,255,.1)] dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset]",
className
)}
{...props}
>
<div>{background}</div>
<div className="pointer-events-none z-10 flex transform-gpu flex-col gap-1 p-6 transition-all duration-300 group-hover:-translate-y-10">
<Icon className="h-12 w-12 origin-left transform-gpu text-neutral-700 transition-all duration-300 ease-in-out group-hover:scale-75" />
<h3 className="text-xl font-semibold text-neutral-700 dark:text-neutral-300">
{name}
</h3>
<p className="max-w-lg text-neutral-400">{description}</p>
</div>
<div className="pointer-events-none absolute inset-0 transform-gpu transition-all duration-300 group-hover:bg-black/[.03] group-hover:dark:bg-neutral-800/10" />
</div>
);
export { BentoCard, BentoGrid };

@ -1,4 +1,3 @@
"use client";
import { BrandingGenericIcon, Discord } from "../icons/branding-icons";
import { Link } from "../../util/link";
import { FooterStatus } from "./status";
@ -8,11 +7,10 @@ import Github from "@/components/ui/github";
import Image from "next/image"
import { usePathname } from "next/navigation";
const hideFooterPages = ["/home"]
const hideFooterPages = ["/home"];
export function Footer() {
const pathname = usePathname();
if (!hideFooterPages.includes(pathname ?? ""))
return (
<footer className="w-full mt-15 border-t border-neutral-500/20 bg-neutral-100 dark:border-neutral-700/50 dark:bg-neutral-900 text-muted-foreground">
@ -52,7 +50,7 @@ export function Footer() {
<div className="flex items-center mb-2 justify-end gap-2">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<DropdownMenuTrigger>
<Button variant="tertiary" size="square-md" className="flex items-center">
<Discord className="w-[1.25em] h-[1.25em]" />
</Button>

@ -90,6 +90,8 @@ export function FontChanger({
return () => clearInterval(interval);
}, []);
console.log(position);
return (
<div className="h-[1.2em] overflow-hidden flex items-center justify-center">
<span

@ -106,13 +106,13 @@ export default function HomePageComponent() {
style={
{
"--gradient-color-1":
resolvedTheme === "dark" ? "#470061" : "#610034",
resolvedTheme === "dark" ? "#043D5D" : "#1F9EA3",
"--gradient-color-2":
resolvedTheme === "dark" ? "#001299" : "#700099",
resolvedTheme === "dark" ? "#032E46" : "#F8BD97",
"--gradient-color-3":
resolvedTheme === "dark" ? "#8d00eb" : "#eb00ac",
resolvedTheme === "dark" ? "#23B684" : "#9E5428",
"--gradient-color-4":
resolvedTheme === "dark" ? "#009de0" : "#0007e0",
resolvedTheme === "dark" ? "#0F595E" : "#EEEEEE",
webKitMaskImage:
"linear-gradient(to top, black, black, transparent)",
maskImage: "linear-gradient(to top, black, black, transparent)",

@ -74,12 +74,10 @@ export function NavBar() {
"w-screen h-[3rem] grid-cols-3 fixed z-10 flex",
"items-center justify-self-start me-auto pl-4 flex-1 transition-all justify-between",
"lg:top-0 max-lg:bottom-0",
showBorder
? "border-b backdrop-blur-xl"
: "max-lg:border-b max-lg:backdrop-blur-xl",
showBorder ? "border-b backdrop-blur-xl" : "max-lg:border-b max-lg:backdrop-blur-xl",
pathname !== null && animatedTopbarPages.includes(pathname)
? "[--animation-delay:1000ms] opacity-0 animate-fade-in"
: "",
: ""
)}
>
<span>
@ -144,24 +142,22 @@ export function NavBar() {
</span>
<span className="mr-3 flex items-center">
<DropdownMenu>
<DropdownMenuTrigger>
<SignedOut>
<DropdownMenuTrigger asChild>
<Button
className={cn(
"rounded-full flex items-center",
pathname !== null && animatedTopbarPages.includes(pathname)
? "[--animation-delay:2000ms] opacity-0 animate-fade-in"
: "",
: ""
)}
size="square-lg"
variant="secondary"
>
<Menu size={16} />
</Button>
</DropdownMenuTrigger>
</SignedOut>
<SignedIn>
<DropdownMenuTrigger asChild>
<Button
size="square-lg"
variant="tertiary"
@ -169,7 +165,7 @@ export function NavBar() {
"rounded-full flex items-center",
pathname !== null && animatedTopbarPages.includes(pathname)
? "[--animation-delay:2000ms] opacity-0 animate-fade-in"
: "",
: ""
)}
>
<NextImage
@ -184,8 +180,8 @@ export function NavBar() {
className="rounded-full"
/>
</Button>
</DropdownMenuTrigger>
</SignedIn>
</DropdownMenuTrigger>
<DropdownMenuContent className="max-w-[280px] w-[280px] mt-2 mr-2">
<MenuDropdown />
</DropdownMenuContent>

@ -2,54 +2,10 @@ import { Button } from "@/components/ui/button";
import type { Filter } from "@/lib/types/filter";
import type { Sort } from "@/lib/types/sort";
import { ModificationFileCreationDialog } from "./modification-file-creation-dialog";
import { useUser } from "@clerk/nextjs";
import { useEffect, useState } from "react";
import { useIframeCommunication } from "@/lib/hooks/use-iframe-communication";
type Action = Filter | Sort | { customAction: string };
export type ClerkEmbeddedFilter<T> = {
type: string;
metadata: T;
};
export function ModificationAction({ value }: { value?: Action }) {
const { isSignedIn, user } = useUser();
const [applied, setApplied] = useState<number | undefined>();
const communication = useIframeCommunication();
const findExisting = () => {
if (!(value !== undefined && "customAction" in value)) {
const filter = value as Filter;
let existing = -1;
if (isSignedIn)
existing = (
(user.unsafeMetadata.filters as Array<
ClerkEmbeddedFilter<unknown>
>) ?? []
).findIndex(
(c) =>
JSON.stringify(c.metadata) ===
JSON.stringify(filter.toIdentifier()) &&
c.type === filter.getSpecificFilterId(),
);
else
existing = (
(JSON.parse(localStorage.getItem("mhsf__filters") ?? "[]") as Array<
ClerkEmbeddedFilter<unknown>
>) ?? []
).findIndex(
(c) =>
JSON.stringify(c.metadata) === JSON.stringify(filter.toIdentifier()) &&
c.type === filter.getSpecificFilterId(),
);
return existing;
}
return -1;
};
useEffect(() => setApplied(findExisting()))
return (
<>
{value !== undefined && "customAction" in value ? (
@ -63,73 +19,7 @@ export function ModificationAction({ value }: { value?: Action }) {
</Button>
</ModificationFileCreationDialog>
) : (
<Button
size="sm"
className="mt-1"
onClick={async () => {
if (value?.type() === "filter") {
const filter = value as Filter;
const existing = findExisting();
if (isSignedIn) {
const existingArray =
(user.unsafeMetadata.filters as Array<
ClerkEmbeddedFilter<unknown>
>) ?? [];
existingArray.splice(existing, 1);
if (existing === -1)
await user.update({
unsafeMetadata: {
...user.unsafeMetadata,
filters: [
{
type: filter.getSpecificFilterId(),
metadata: filter.toIdentifier(),
},
...((user.unsafeMetadata.filters as Array<
ClerkEmbeddedFilter<unknown>
>) ?? []),
] as Array<ClerkEmbeddedFilter<unknown>>,
},
});
else
await user.update({
unsafeMetadata: {
filters: existingArray,
...user.unsafeMetadata,
},
});
} else {
const existingArray =
(JSON.parse(
localStorage.getItem("mhsf__filters") ?? "[]",
) as Array<ClerkEmbeddedFilter<unknown>>) ?? [];
existingArray.splice(existing, 1);
if (existing === -1)
localStorage.setItem(
"mhsf__filters",
JSON.stringify([
{
type: filter.getSpecificFilterId(),
metadata: filter.toIdentifier(),
},
...((JSON.parse(
localStorage.getItem("mhsf__filters") ?? "[]",
) as Array<ClerkEmbeddedFilter<unknown>>) ?? []),
]),
);
else
localStorage.setItem("mhsf__filters", JSON.stringify(existingArray));
}
setApplied(findExisting());
}
communication.fromIframe.send("rerender-servers", {});
}}
>
{applied === -1 ? "A" : "Una"}pply
</Button>
<Button size="sm">Apply</Button>
)}
</>
);

@ -41,9 +41,6 @@ export function ModificationFrame() {
if (c.from === "iframe")
communication.toIframe.send("ping", {from: "top-layer"})
})
communication.toIframe.handle("rerender-servers", (c) => {
window.dispatchEvent(new Event("update-modification-stack"))
})
}, [ref])
return <iframe ref={ref} src="/servers/embedded/sl-modification-frame" height={800} title="Server-list Modification Frame" />

@ -36,63 +36,15 @@ import { miniMessage } from "minimessage-js";
import { toast } from "sonner";
import { cn } from "@/lib/utils";
import { Material } from "@/components/ui/material";
import { useState } from "react";
import { useMHSFServer } from "@/lib/hooks/use-mhsf-server";
import Markdown from "react-markdown";
import { Button } from "@/components/ui/button";
import { Ellipsis, EllipsisVertical, Shuffle } from "lucide-react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { RearrangeDrawer } from "../rearrange/rearrange-drawer";
export function MOTDRow({
server,
mhsfData,
}: { server: ServerResponse; mhsfData: ReturnType<typeof useMHSFServer> }) {
export function MOTDRow({ server }: { server: ServerResponse }) {
const clipboard = useClipboard();
const [tab, setTab] = useState("motd");
return (
<Material className="p-4 relative h-[250px]">
<span className="flex gap-4 justify-between items-center">
<span className="flex gap-4 items-center">
<strong className="text-lg max-lg:hidden">
{tab === "motd" ? "MOTD" : "Description"}
</strong>
<button
type="button"
className={cn(
"text-sm cursor-pointer hover:bg-slate-100 dark:hover:bg-zinc-700/30 transition-all duration-75 disabled:opacity-50 disabled:pointer-events-none",
"rounded-xl px-2 flex items-center gap-2",
tab === "motd" && "bg-slate-100 dark:bg-zinc-700/30 font-medium",
)}
onClick={() => setTab("motd")}
>
MOTD
</button>
{mhsfData.server?.customizationData.description !== undefined && (
<button
type="button"
className={cn(
"text-sm cursor-pointer hover:bg-slate-100 dark:hover:bg-zinc-700/30 transition-all duration-75 disabled:opacity-50 disabled:pointer-events-none",
"rounded-xl px-2 flex items-center gap-2",
tab === "description" &&
"bg-slate-100 dark:bg-zinc-700/30 font-medium",
)}
onClick={() => setTab("description")}
>
Description
</button>
)}
</span>
</span>
<strong className="text-lg">MOTD</strong>
<br />
<Separator className="my-2" />
{tab === "motd" && (
<>
<MOTDRenderer
className={cn("mt-2 break-all overflow-y-auto max-h-[150px]")}
minecraftFont
@ -107,7 +59,7 @@ export function MOTDRow({
type="button"
onClick={() => {
clipboard.writeText(
miniMessage().toHTML(miniMessage().deserialize(server.motd)),
miniMessage().toHTML(miniMessage().deserialize(server.motd))
);
toast.success("Copied to clipboard.");
}}
@ -115,13 +67,6 @@ export function MOTDRow({
click to copy HTML
</button>
</small>
</>
)}
{tab === "description" && (
<div className="prose mt-2 break-words overflow-y-auto max-h-[175px] dark:prose-invert">
<Markdown>{mhsfData.server?.customizationData.description}</Markdown>
</div>
)}
</Material>
);
}

@ -38,8 +38,8 @@ export function ServerRows({ server, mhsfData }: { server: ServerResponse, mhsfD
const clipboard = useClipboard();
return (
<span className="lg:grid lg:grid-cols-2 w-full gap-3">
<MOTDRow server={server} mhsfData={mhsfData}/>
<span className="lg:grid lg:grid-cols-3 w-full gap-3">
<MOTDRow server={server} />
<StatisticsMainRow server={server} mhsfData={mhsfData} />
</span>
);

@ -32,7 +32,7 @@ export function StatisticsMainRow({
return (
<Material
className="relative h-[250px] max-lg:mt-3"
className="relative col-span-2 h-[250px] max-lg:mt-3"
padding="none"
>
<div className="p-4">

@ -1,62 +0,0 @@
/*
* MHSF, Minehut Server List
* All external content is rather licensed under the ECA Agreement
* located here: https://mhsf.app/docs/legal/external-content-agreement
*
* All code under MHSF is licensed under the MIT License
* by open source contributors
*
* Copyright (c) 2025 dvelo
*
* 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.
*/
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
import { useUser } from "@clerk/nextjs";
import { Editor } from "@monaco-editor/react";
import { useEffect, useState, type ReactNode } from "react";
export function ClerkMetadataPopup({children}: {children: ReactNode | ReactNode[] | undefined}) {
const [mdType, setMDType] = useState<"public" | "unsafe" | null>(null)
const [open, setOpen] = useState(false);
const {user} = useUser();
useEffect(() => {
window.addEventListener("open-public-clerkmd", () => {
setMDType("public")
setOpen(true);
})
window.addEventListener("open-unsafe-clerkmd", () => {
setMDType("unsafe")
setOpen(true);
})
})
return <>
{children}
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent className="min-w-[850px]">
<DialogTitle>{mdType?.toLocaleUpperCase()} metadata</DialogTitle>
<Editor options={{domReadOnly: true, readOnly: true}} height={500} width={800} language="json" value={JSON.stringify(mdType === "public" ? user?.publicMetadata : user?.unsafeMetadata, null, 2)}/>
</DialogContent>
</Dialog>
</>
}

@ -29,30 +29,14 @@
*/
import { Material } from "@/components/ui/material";
import {
Setting,
SettingContent,
SettingDescription,
SettingMeta,
SettingTitle,
} from "./setting";
import { Setting, SettingContent, SettingDescription, SettingMeta, SettingTitle } from "./setting";
import { Button } from "@/components/ui/button";
import { AnimatedText } from "@/components/ui/animated-text";
import { useEffect, useState } from "react";
import { useState } from "react";
import { loadingList } from "../server-page/util";
import { ClerkMetadataPopup } from "./clerk-metadata-popup";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Switch } from "@/components/ui/switch";
import { Link } from "@/components/util/link";
import { useSettingsStore } from "@/lib/hooks/use-settings-store";
export function DebugSettings() {
const [randomText, setRandomText] = useState("");
const [randomText, setRandomText] = useState("")
return (
<Material className="mt-6 grid gap-4">
@ -60,46 +44,23 @@ export function DebugSettings() {
<Setting>
<SettingContent>
<SettingMeta>
<SettingTitle>Generate loading text</SettingTitle>
<SettingTitle>
Generate loading text
</SettingTitle>
<SettingDescription>
Generate a random loading text
</SettingDescription>
</SettingMeta>
<div className="block pb-6">
<Button
onClick={() => {
setRandomText(
loadingList[Math.floor(Math.random() * loadingList.length)],
);
}}
>
<Button onClick={() => {
setRandomText(loadingList[Math.floor(Math.random() * loadingList.length)])
}}>
Generate
</Button>
<AnimatedText className="font-bold" text={randomText + "..."} />
<AnimatedText className="font-bold" text={randomText + "..."}/>
</div>
</SettingContent>
</Setting>
<ClerkMetadataPopup>
<Setting>
<SettingContent>
<SettingMeta>
<SettingTitle>View Clerk metadata</SettingTitle>
<SettingDescription>
View any Clerk metadata for your user.
</SettingDescription>
</SettingMeta>
<DropdownMenu>
<DropdownMenuTrigger>
<Button>Open metadata</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={() => window.dispatchEvent(new Event("open-public-clerkmd"))}>Public</DropdownMenuItem>
<DropdownMenuItem onClick={() => window.dispatchEvent(new Event("open-unsafe-clerkmd"))}>Unsafe</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SettingContent>
</Setting>
</ClerkMetadataPopup>
</Material>
);
}

@ -61,7 +61,7 @@ const badgeVariants = cva(
"purple-subtle": `bg-purple-100 dark:bg-purple-500/20 text-purple-700 dark:text-purple-400
ring-purple-400 dark:ring-purple-500/30`,
rainbow:
"text-white ring-transparent z-10 [background:_linear-gradient(45deg,rgba(255,_0,_0,_1)_0%,rgba(255,_154,_0,_1)_10%,rgba(208,_222,_33,_1)_20%,rgba(79,_220,_74,_1)_30%,rgba(63,_218,_216,_1)_40%,rgba(47,_201,_226,_1)_50%,rgba(28,_127,_238,_1)_60%,rgba(95,_21,_242,_1)_70%,rgba(186,_12,_248,_1)_80%,rgba(251,_7,_217,_1)_90%,rgba(255,_0,_0,_1)_100%);] backdrop-blur-sm opacity-60 ",
"text-white ring-transparent [background:_linear-gradient(45deg,rgba(255,_0,_0,_1)_0%,rgba(255,_154,_0,_1)_10%,rgba(208,_222,_33,_1)_20%,rgba(79,_220,_74,_1)_30%,rgba(63,_218,_216,_1)_40%,rgba(47,_201,_226,_1)_50%,rgba(28,_127,_238,_1)_60%,rgba(95,_21,_242,_1)_70%,rgba(186,_12,_248,_1)_80%,rgba(251,_7,_217,_1)_90%,rgba(255,_0,_0,_1)_100%);] backdrop-blur-sm opacity-60 ",
custom: "",
},
allowIconOnly: {

@ -28,8 +28,6 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
"use client";
import { useTheme } from "@/lib/hooks/use-theme";
import type { SVGProps } from "react";
const Github = (props: SVGProps<SVGSVGElement>) => {

@ -30,13 +30,11 @@
import {
ArrowDownUpIcon,
ServerCog,
SlidersHorizontal,
type LucideIcon,
} from "lucide-react";
import { type Filter } from "../lib/types/filter";
import type { Filter } from "../lib/types/filter";
import type { Sort } from "../lib/types/sort";
import { TagFilter } from "@/lib/types/filters/tag-filter";
type ModDBCategory = {
displayTitle: string;
@ -80,18 +78,5 @@ export const serverModDB: ModDBCategory[] = [
__custom: true,
// Entries are already pre-loaded.
entries: []
},
{
displayTitle: "Tag Filters",
description: "These are filters that are associated with an assortment of tags.",
entries: [
{
name: "Always Online",
description: "All servers that are always online.",
color: "#a380e0",
value: new TagFilter(2, false),
icon: ServerCog
}
]
}
];

@ -36,12 +36,10 @@ import { tryCatch } from "../try-catch";
import { transpileTypeScript } from "@/app/(sl-modification-frame)/servers/embedded/sl-modification-frame/file/[filename]/page";
import { useUser } from "@clerk/nextjs";
import type { ClerkCustomActivatedModification } from "@/components/feat/server-list/modification/modification-file-creation-dialog";
import { ClerkEmbeddedFilter } from "@/components/feat/server-list/modification/modification-action";
import { supportedFilters } from "../types/filter";
type EmbeddedFilter = {
identifier: string;
functionFilter: (server: OnlineServer) => (boolean | Promise<boolean>);
functionFilter: (server: OnlineServer) => boolean;
};
type SortFunction<K> = (object1: K, object2: K) => number;
@ -59,20 +57,23 @@ export function useFilters(data: OnlineServer[]) {
const [sort, setSort] = useState<SortFunction<OnlineServer> | null>(null);
const { user, isSignedIn } = useUser();
const updateServers = async (newFilters: EmbeddedFilter[]) => {
const modificationMap = await Promise.all(data.map((v) =>
Promise.all(newFilters.map(async (c) => c.functionFilter(v))),
));
const updateServers = (newFilters: EmbeddedFilter[]) => {
const modificationMap = data.map((v) =>
newFilters.map((c) => c.functionFilter(v)),
);
const resultData = data.filter(
(_, i) => !modificationMap[i].includes(false),
);
const sortedData = sort === null ? resultData : resultData.sort(sort);
console.log({ sortedData, modificationMap, resultData, data, newFilters });
console.table({ sortedData, modificationMap, resultData, data });
if (sortedData.length !== 0) setFilteredData(sortedData);
if (sortedData.length !== 0)
setFilteredData(sortedData);
};
// biome-ignore lint: bruh
useEffect(() => {
if (filteredData.length === 0 || data.length === 0) {
window.dispatchEvent(new Event("update-modification-stack"));
@ -212,13 +213,7 @@ export function useFilters(data: OnlineServer[]) {
if (!t)
window.addEventListener("update-modification-stack", async () => {
await user?.reload();
setLoading(true);
let newFilters: EmbeddedFilter[] = [];
const filters =
((isSignedIn ? user.unsafeMetadata.filters : JSON.parse(localStorage.getItem("mhsf__filters") ?? "[]")) as Array<
ClerkEmbeddedFilter<unknown>
>) ?? [];
if (isSignedIn) {
const activatedModifications =
(user.unsafeMetadata
@ -255,66 +250,40 @@ export function useFilters(data: OnlineServer[]) {
toast.error(
`Couldn't enable modification '${c.friendlyName}'. Please lint and test again.`,
);
return {
identifier: `file-${c.originalFileName}.ts`,
functionFilter: () => true,
};
return { identifier: `file-${c.originalFileName}.ts`, functionFilter: () => true };
}
if (typeof filterFunc === "function") {
return {
identifier: `file-${c.originalFileName}.ts`,
functionFilter: filterFunc,
};
return { identifier: `file-${c.originalFileName}.ts`, functionFilter: filterFunc };
}
toast.error(
`Couldn't enable modification '${c.friendlyName}'. Please lint and test again.`,
);
return {
identifier: `file-${c.originalFileName}.ts`,
functionFilter: () => true,
};
return { identifier: `file-${c.originalFileName}.ts`, functionFilter: () => true };
}),
)) as EmbeddedFilter[];
// avoid duplicates
// biome-ignore lint/complexity/noForEach:
resolvedModifications.forEach((item) => {
setFilters((c) => {
if (c.findIndex((i) => i.identifier === item.identifier) === -1)
return [...c, item];
return c;
});
return [
...c,
item
]
else return c;
});
})
newFilters = resolvedModifications.map((item) => {
return item;
});
}
// biome-ignore lint/complexity/noForEach:
filters.forEach((filter) => {
// Get back the filter type from the namespace
const filterType = supportedFilters.find(
(t) => filter.type === t.ns,
);
// Get back a filter with associated metadata
const parsedFilter = filterType?.fi(
filter.metadata as {
[key: string]: string | number | boolean;
},
);
newFilters.push({
identifier: filterType?.ns + (Math.random() * Math.random() * Math.random()).toString(),
functionFilter: (server: OnlineServer) => parsedFilter?.applyToServer({ online: server }) ?? true
})
});
console.log(newFilters);
await updateServers(newFilters);
updateServers(newFilters);
});
}, [data]);
console.log(filters);
@ -324,9 +293,7 @@ export function useFilters(data: OnlineServer[]) {
testModeEnabled,
testModeLoading,
testModeStatus,
filterCount:
filters.filter((item, index, array) => array.indexOf(item) === index)
.length + (sort === null ? 1 : 0),
filterCount: filters.filter((item, index, array) => array.indexOf(item) === index).length + (sort === null ? 1 : 0),
loading,
};
}

@ -1,44 +0,0 @@
/*
* MHSF, Minehut Server List
* All external content is rather licensed under the ECA Agreement
* located here: https://mhsf.app/docs/legal/external-content-agreement
*
* All code under MHSF is licensed under the MIT License
* by open source contributors
*
* Copyright (c) 2025 dvelo
*
* 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.
*/
import { allTags } from "@/config/tags"
import { useUser } from "@clerk/nextjs"
export function useModificationsChange() {
const {isSignedIn} = useUser()
return {
addFilterData: async (namespace: string, identifier: { [key: string]: string | number | boolean }) => {
if (isSignedIn) {
}
}
}
}

@ -74,24 +74,3 @@ export function useSettingsStore() {
},
};
}
// An exact copy of the API without Clerk
export function useNoClerkSettingsStore() {
return {
get: (key: string) => {
if (localStorage.getItem(key) === "true")
return true;
if (localStorage.getItem(key) === "false")
return false;
return localStorage.getItem(key);
},
set: async (
key: string,
value: string | boolean,
userEntry: boolean,
__unsafeMetadata = false
) => {
localStorage.setItem(key, value.toString());
},
};
}

@ -28,39 +28,10 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
import { allTags } from "@/config/tags";
import type { OnlineServer, ServerResponse } from "./mh-server";
import type { MHSFData } from "./data";
import { TagFilter } from "./filters/tag-filter";
import { CategoryFilter } from "./filters/category-filter";
import type { OnlineServer } from "./mh-server";
/* Any filter that can be converted back and forth from a string or a Filter object */
export interface Filter {
type(): "filter";
toIdentifier(): { [key: string]: string | number | boolean };
getSpecificFilterId(): string;
fromIdentifier(identifier: {
[key: string]: string | number | boolean;
}): Filter;
applyToServer(server: {
online?: OnlineServer;
server?: ServerResponse;
mhsfData?: MHSFData;
}): Promise<boolean>;
toIdentifier(): string;
fromIdentifier(identifier: string): Filter;
applyToServer(server: OnlineServer): boolean;
}
export const supportedFilters: {
ns: string;
fi: (identifier: {
[key: string]: string | number | boolean;
}) => Filter;
}[] = [
{
ns: "app.mhsf.filter.tagFilter",
fi: new TagFilter(0, false).fromIdentifier
},
{
ns: "app.mhsf.filter.categoryFilter",
fi: new CategoryFilter(0).fromIdentifier
}
];

@ -1,64 +0,0 @@
/*
* MHSF, Minehut Server List
* All external content is rather licensed under the ECA Agreement
* located here: https://mhsf.app/docs/legal/external-content-agreement
*
* All code under MHSF is licensed under the MIT License
* by open source contributors
*
* Copyright (c) 2025 dvelo
*
* 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.
*/
import { allCategories } from "@/config/tags";
import type { MHSFData } from "../data";
import type { Filter } from "../filter";
import type { OnlineServer, ServerResponse } from "../mh-server";
export class CategoryFilter implements Filter {
categoryIndex: number;
type(): "filter" {
return "filter";
}
toIdentifier(): { [key: string]: string | number | boolean } {
return { categoryIndex: this.categoryIndex };
}
fromIdentifier(identifier: { [key: string]: string | number | boolean; }): Filter {
return new CategoryFilter(identifier.categoryIndex as number);
}
getSpecificFilterId(): string {
return "app.mhsf.filter.categoryFilter";
}
applyToServer(server: { online?: OnlineServer; server?: ServerResponse; mhsfData?: MHSFData; }): Promise<boolean> {
if (server.online !== undefined)
return allCategories[this.categoryIndex].condition(server.online);
return new Promise((r) => r(true));
}
constructor(categoryIndex: number) {
this.categoryIndex = categoryIndex;
}
}

@ -1,90 +0,0 @@
/*
* MHSF, Minehut Server List
* All external content is rather licensed under the ECA Agreement
* located here: https://mhsf.app/docs/legal/external-content-agreement
*
* All code under MHSF is licensed under the MIT License
* by open source contributors
*
* Copyright (c) 2025 dvelo
*
* 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.
*/
import { allTags } from "@/config/tags";
import type { MHSFData } from "../data";
import type { OnlineServer, ServerResponse } from "../mh-server";
import type { Filter } from "../filter";
export class TagFilter implements Filter {
tagId: string;
opposite: boolean;
type(): "filter" {
return "filter";
}
toIdentifier(): { [key: string]: string | number | boolean } {
return { tagId: this.tagId, opposite: this.opposite };
}
getSpecificFilterId(): string {
return "app.mhsf.filter.tagFilter";
}
fromIdentifier(identifier: {
[key: string]: string | number | boolean;
}): Filter {
return new TagFilter(identifier.tagId as string, identifier.opposite as boolean);
}
constructor(tagIndex: number | string, opposite: boolean) {
if (typeof tagIndex === "string") this.tagId = tagIndex;
else this.tagId = btoa(allTags[tagIndex].docsName);
this.opposite = opposite;
}
applyToServer(server: {
online?: OnlineServer;
server?: ServerResponse;
mhsfData?: MHSFData;
}): Promise<boolean> {
const result = (
(
allTags.find((c) => btoa(c.docsName) === this.tagId) ?? {
condition: () => true,
}
).condition ?? (() => true)
)(server);
console.log(result, server.online?.name, (
allTags.find((c) => btoa(c.docsName) === this.tagId) ?? {
condition: () => true,
}
));
if (typeof result === "boolean")
return new Promise((r) => r(this.opposite ? !result : result))
return new Promise((r) => {
result.then((c) => r(this.opposite ? !c : c))
});
}
}

@ -31,11 +31,7 @@
import type { OnlineServer } from "./mh-server";
export interface Sort {
type(): "sort";
toIdentifier(): { [key: string]: string | number | boolean };
getSpecificSortId(): string;
fromIdentifier(identifier: {
[key: string]: string | number | boolean;
}): Sort;
toIdentifier(): string;
fromIdentifier(identifier: string): Sort;
sortToServers(serverA: OnlineServer, serverB: OnlineServer): number;
}

@ -49,8 +49,6 @@ export default process.env.NEXT_PUBLIC_IS_AUTH === "true"
? clerkMiddleware(async (auth, req) => {
const authRes = await auth();
const client = await clerkClient();
const requestHeaders = new Headers(req.headers);
requestHeaders.set("x-url", req.url);
if (isRootRoute(req)) {
switch (authRes.userId === null) {
@ -72,12 +70,6 @@ export default process.env.NEXT_PUBLIC_IS_AUTH === "true"
new URL(`/server/v2/minehut/${minehutRes.server._id}`, req.url),
);
}
return NextResponse.next({
request: {
headers: requestHeaders,
},
});
})
: (request: NextRequest) => {};

@ -45,6 +45,8 @@ export default async function handler(
const result = await betterStackResult.json();
const url = await betterStackURL.json();
console.log(result)
const filtered = result.data.filter(
(c: any) =>
c.attributes.ends_at === null &&

@ -57,7 +57,7 @@ export default async function handler(
return res.status(401).json({ error: "Unauthorized" });
}
if (
(await (await clerkClient()).users.getUser(userId)).publicMetadata.player ===
(await (await clerkClient()).users.getUser(userId)).publicMetadata.player ==
undefined
) {
return res.status(401).json({ error: "Account not linked" });
@ -68,7 +68,7 @@ export default async function handler(
const db = client.db(process.env.CUSTOM_MONGO_DB ?? "mhsf");
const collection = db.collection("owned-servers");
if ((await collection.findOne({ server: server })) === undefined) {
if ((await collection.findOne({ server: server })) == undefined) {
const mh = await fetch(
process.env.MHSF_BACKEND_API_LOCATION ??
"https://api.minehut.com/servers",
@ -116,7 +116,7 @@ export default async function handler(
.send({ message: "The linked account doesn't own the server." });
}
}
if (i === servers.length) {
if (i == servers.length) {
// Close the database, but don't close this
// serverless instance until it happens
waitUntil(client.close());

285
yarn.lock

@ -1059,13 +1059,6 @@
optionalDependencies:
"@img/sharp-libvips-darwin-arm64" "1.0.4"
"@img/sharp-darwin-arm64@0.34.1":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.1.tgz#e79a4756bea9a06a7aadb4391ee53cb154a4968c"
integrity sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==
optionalDependencies:
"@img/sharp-libvips-darwin-arm64" "1.1.0"
"@img/sharp-darwin-x64@0.33.5":
version "0.33.5"
resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz#e03d3451cd9e664faa72948cc70a403ea4063d61"
@ -1073,98 +1066,46 @@
optionalDependencies:
"@img/sharp-libvips-darwin-x64" "1.0.4"
"@img/sharp-darwin-x64@0.34.1":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.1.tgz#f1f1d386719f6933796415d84937502b7199a744"
integrity sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==
optionalDependencies:
"@img/sharp-libvips-darwin-x64" "1.1.0"
"@img/sharp-libvips-darwin-arm64@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz#447c5026700c01a993c7804eb8af5f6e9868c07f"
integrity sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==
"@img/sharp-libvips-darwin-arm64@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz#843f7c09c7245dc0d3cfec2b3c83bb08799a704f"
integrity sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==
"@img/sharp-libvips-darwin-x64@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz#e0456f8f7c623f9dbfbdc77383caa72281d86062"
integrity sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==
"@img/sharp-libvips-darwin-x64@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz#1239c24426c06a8e833815562f78047a3bfbaaf8"
integrity sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==
"@img/sharp-libvips-linux-arm64@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz#979b1c66c9a91f7ff2893556ef267f90ebe51704"
integrity sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==
"@img/sharp-libvips-linux-arm64@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz#20d276cefd903ee483f0441ba35961679c286315"
integrity sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==
"@img/sharp-libvips-linux-arm@1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz#99f922d4e15216ec205dcb6891b721bfd2884197"
integrity sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==
"@img/sharp-libvips-linux-arm@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz#067c0b566eae8063738cf1b1db8f8a8573b5465c"
integrity sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==
"@img/sharp-libvips-linux-ppc64@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz#682334595f2ca00e0a07a675ba170af165162802"
integrity sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==
"@img/sharp-libvips-linux-s390x@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz#f8a5eb1f374a082f72b3f45e2fb25b8118a8a5ce"
integrity sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==
"@img/sharp-libvips-linux-s390x@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz#82fcd68444b3666384235279c145c2b28d8ee302"
integrity sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==
"@img/sharp-libvips-linux-x64@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz#d4c4619cdd157774906e15770ee119931c7ef5e0"
integrity sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==
"@img/sharp-libvips-linux-x64@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz#65b2b908bf47156b0724fde9095676c83a18cf5a"
integrity sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==
"@img/sharp-libvips-linuxmusl-arm64@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz#166778da0f48dd2bded1fa3033cee6b588f0d5d5"
integrity sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==
"@img/sharp-libvips-linuxmusl-arm64@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz#72accf924e80b081c8db83b900b444a67c203f01"
integrity sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==
"@img/sharp-libvips-linuxmusl-x64@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz#93794e4d7720b077fcad3e02982f2f1c246751ff"
integrity sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==
"@img/sharp-libvips-linuxmusl-x64@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz#1fa052737e203f46bf44192acd01f9faf11522d7"
integrity sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==
"@img/sharp-linux-arm64@0.33.5":
version "0.33.5"
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz#edb0697e7a8279c9fc829a60fc35644c4839bb22"
@ -1172,13 +1113,6 @@
optionalDependencies:
"@img/sharp-libvips-linux-arm64" "1.0.4"
"@img/sharp-linux-arm64@0.34.1":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.1.tgz#c36ef964499b8cfc2d2ed88fe68f27ce41522c80"
integrity sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==
optionalDependencies:
"@img/sharp-libvips-linux-arm64" "1.1.0"
"@img/sharp-linux-arm@0.33.5":
version "0.33.5"
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz#422c1a352e7b5832842577dc51602bcd5b6f5eff"
@ -1186,13 +1120,6 @@
optionalDependencies:
"@img/sharp-libvips-linux-arm" "1.0.5"
"@img/sharp-linux-arm@0.34.1":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.1.tgz#c96e38ff028d645912bb0aa132a7178b96997866"
integrity sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==
optionalDependencies:
"@img/sharp-libvips-linux-arm" "1.1.0"
"@img/sharp-linux-s390x@0.33.5":
version "0.33.5"
resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz#f5c077926b48e97e4a04d004dfaf175972059667"
@ -1200,13 +1127,6 @@
optionalDependencies:
"@img/sharp-libvips-linux-s390x" "1.0.4"
"@img/sharp-linux-s390x@0.34.1":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.1.tgz#8ac58d9a49dcb08215e76c8d450717979b7815c3"
integrity sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==
optionalDependencies:
"@img/sharp-libvips-linux-s390x" "1.1.0"
"@img/sharp-linux-x64@0.33.5":
version "0.33.5"
resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz#d806e0afd71ae6775cc87f0da8f2d03a7c2209cb"
@ -1214,13 +1134,6 @@
optionalDependencies:
"@img/sharp-libvips-linux-x64" "1.0.4"
"@img/sharp-linux-x64@0.34.1":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.1.tgz#3d8652efac635f0dba39d5e3b8b49515a2b2dee1"
integrity sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==
optionalDependencies:
"@img/sharp-libvips-linux-x64" "1.1.0"
"@img/sharp-linuxmusl-arm64@0.33.5":
version "0.33.5"
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz#252975b915894fb315af5deea174651e208d3d6b"
@ -1228,13 +1141,6 @@
optionalDependencies:
"@img/sharp-libvips-linuxmusl-arm64" "1.0.4"
"@img/sharp-linuxmusl-arm64@0.34.1":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.1.tgz#b267e6a3e06f9e4d345cde471e5480c5c39e6969"
integrity sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==
optionalDependencies:
"@img/sharp-libvips-linuxmusl-arm64" "1.1.0"
"@img/sharp-linuxmusl-x64@0.33.5":
version "0.33.5"
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz#3f4609ac5d8ef8ec7dadee80b560961a60fd4f48"
@ -1242,13 +1148,6 @@
optionalDependencies:
"@img/sharp-libvips-linuxmusl-x64" "1.0.4"
"@img/sharp-linuxmusl-x64@0.34.1":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.1.tgz#a8dee4b6227f348c4bbacaa6ac3dc584a1a80391"
integrity sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==
optionalDependencies:
"@img/sharp-libvips-linuxmusl-x64" "1.1.0"
"@img/sharp-wasm32@0.33.5":
version "0.33.5"
resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz#6f44f3283069d935bb5ca5813153572f3e6f61a1"
@ -1256,33 +1155,16 @@
dependencies:
"@emnapi/runtime" "^1.2.0"
"@img/sharp-wasm32@0.34.1":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.34.1.tgz#f7dfd66b6c231269042d3d8750c90f28b9ddcba1"
integrity sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==
dependencies:
"@emnapi/runtime" "^1.4.0"
"@img/sharp-win32-ia32@0.33.5":
version "0.33.5"
resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz#1a0c839a40c5351e9885628c85f2e5dfd02b52a9"
integrity sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==
"@img/sharp-win32-ia32@0.34.1":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.1.tgz#4bc293705df76a5f0a02df66ca3dc12e88f61332"
integrity sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==
"@img/sharp-win32-x64@0.33.5":
version "0.33.5"
resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz#56f00962ff0c4e0eb93d34a047d29fa995e3e342"
integrity sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==
"@img/sharp-win32-x64@0.34.1":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.1.tgz#8a7922fec949f037c204c79f6b83238d2482384b"
integrity sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==
"@inngest/ai@^0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@inngest/ai/-/ai-0.1.3.tgz#25a86d08a8fe7288fdcde1bb02ad084ed3fa2166"
@ -1806,10 +1688,10 @@
resolved "https://registry.yarnpkg.com/@next/env/-/env-15.1.6.tgz#2fa863d8c568a56b1c8328a86e621b8bdd4f2a20"
integrity sha512-d9AFQVPEYNr+aqokIiPLNK/MTyt3DWa/dpKveiAaVccUadFbhFEvY6FXYX2LJO2Hv7PHnLBu2oWwB4uBuHjr/w==
"@next/env@15.3.1":
version "15.3.1"
resolved "https://registry.yarnpkg.com/@next/env/-/env-15.3.1.tgz#fca98dcb90d92d555972cdbf03adf9aa982e2115"
integrity sha512-cwK27QdzrMblHSn9DZRV+DQscHXRuJv6MydlJRpFSqJWZrTYMLzKDeyueJNN9MGd8NNiUKzDQADAf+dMLXX7YQ==
"@next/env@15.2.0":
version "15.2.0"
resolved "https://registry.yarnpkg.com/@next/env/-/env-15.2.0.tgz#4c3508ca2c0bb2bc324066818bb8d0415f767641"
integrity sha512-eMgJu1RBXxxqqnuRJQh5RozhskoNUDHBFybvi+Z+yK9qzKeG7dadhv/Vp1YooSZmCnegf7JxWuapV77necLZNA==
"@next/env@^13.4.3":
version "13.5.11"
@ -1835,80 +1717,80 @@
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.6.tgz#92f99badab6cb41f4c5c11a3feffa574bd6a9276"
integrity sha512-u7lg4Mpl9qWpKgy6NzEkz/w0/keEHtOybmIl0ykgItBxEM5mYotS5PmqTpo+Rhg8FiOiWgwr8USxmKQkqLBCrw==
"@next/swc-darwin-arm64@15.3.1":
version "15.3.1"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.1.tgz#8f9589aed9f6816687440aa36a86376b3a16af58"
integrity sha512-hjDw4f4/nla+6wysBL07z52Gs55Gttp5Bsk5/8AncQLJoisvTBP0pRIBK/B16/KqQyH+uN4Ww8KkcAqJODYH3w==
"@next/swc-darwin-arm64@15.2.0":
version "15.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.2.0.tgz#51ebba2162330ee3e8b3412bf31defd94a7b85e7"
integrity sha512-rlp22GZwNJjFCyL7h5wz9vtpBVuCt3ZYjFWpEPBGzG712/uL1bbSkS675rVAUCRZ4hjoTJ26Q7IKhr5DfJrHDA==
"@next/swc-darwin-x64@15.1.6":
version "15.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.6.tgz#f56f4f8d5f6cb5d3915912ac95590d387f897da5"
integrity sha512-x1jGpbHbZoZ69nRuogGL2MYPLqohlhnT9OCU6E6QFewwup+z+M6r8oU47BTeJcWsF2sdBahp5cKiAcDbwwK/lg==
"@next/swc-darwin-x64@15.3.1":
version "15.3.1"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.1.tgz#2df013226d848394ed7307188c141f0e6da4ab3e"
integrity sha512-q+aw+cJ2ooVYdCEqZVk+T4Ni10jF6Fo5DfpEV51OupMaV5XL6pf3GCzrk6kSSZBsMKZtVC1Zm/xaNBFpA6bJ2g==
"@next/swc-darwin-x64@15.2.0":
version "15.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.2.0.tgz#90fd6c6cee494d4348342434cfb9ca9506eae895"
integrity sha512-DiU85EqSHogCz80+sgsx90/ecygfCSGl5P3b4XDRVZpgujBm5lp4ts7YaHru7eVTyZMjHInzKr+w0/7+qDrvMA==
"@next/swc-linux-arm64-gnu@15.1.6":
version "15.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.6.tgz#0aaffae519c93d1006419d7b98c34ebfd80ecacd"
integrity sha512-jar9sFw0XewXsBzPf9runGzoivajeWJUc/JkfbLTC4it9EhU8v7tCRLH7l5Y1ReTMN6zKJO0kKAGqDk8YSO2bg==
"@next/swc-linux-arm64-gnu@15.3.1":
version "15.3.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.1.tgz#d1c4e24b2b27c36a7ebc21ae0573e9e98f794143"
integrity sha512-wBQ+jGUI3N0QZyWmmvRHjXjTWFy8o+zPFLSOyAyGFI94oJi+kK/LIZFJXeykvgXUk1NLDAEFDZw/NVINhdk9FQ==
"@next/swc-linux-arm64-gnu@15.2.0":
version "15.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.2.0.tgz#f10a26cdbacf2e3de2a02a926c72857b3cb613e1"
integrity sha512-VnpoMaGukiNWVxeqKHwi8MN47yKGyki5q+7ql/7p/3ifuU2341i/gDwGK1rivk0pVYbdv5D8z63uu9yMw0QhpQ==
"@next/swc-linux-arm64-musl@15.1.6":
version "15.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.6.tgz#e7398d3d31ca60033f708a718cd6c31edcee2e9a"
integrity sha512-+n3u//bfsrIaZch4cgOJ3tXCTbSxz0s6brJtU3SzLOvkJlPQMJ+eHVRi6qM2kKKKLuMY+tcau8XD9CJ1OjeSQQ==
"@next/swc-linux-arm64-musl@15.3.1":
version "15.3.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.1.tgz#bce27533f9f046800f850a9c20832e8c15b10955"
integrity sha512-IIxXEXRti/AulO9lWRHiCpUUR8AR/ZYLPALgiIg/9ENzMzLn3l0NSxVdva7R/VDcuSEBo0eGVCe3evSIHNz0Hg==
"@next/swc-linux-arm64-musl@15.2.0":
version "15.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.2.0.tgz#1821c9a1dd17c441d8182f5cefd586f7902fcdb5"
integrity sha512-ka97/ssYE5nPH4Qs+8bd8RlYeNeUVBhcnsNUmFM6VWEob4jfN9FTr0NBhXVi1XEJpj3cMfgSRW+LdE3SUZbPrw==
"@next/swc-linux-x64-gnu@15.1.6":
version "15.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.6.tgz#d76c72508f4d79d6016cab0c52640b93e590cffb"
integrity sha512-SpuDEXixM3PycniL4iVCLyUyvcl6Lt0mtv3am08sucskpG0tYkW1KlRhTgj4LI5ehyxriVVcfdoxuuP8csi3kQ==
"@next/swc-linux-x64-gnu@15.3.1":
version "15.3.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.1.tgz#f90558d93bc25e01b0b271725e291863286753c4"
integrity sha512-bfI4AMhySJbyXQIKH5rmLJ5/BP7bPwuxauTvVEiJ/ADoddaA9fgyNNCcsbu9SlqfHDoZmfI6g2EjzLwbsVTr5A==
"@next/swc-linux-x64-gnu@15.2.0":
version "15.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.2.0.tgz#522f55c7672346bab43bce0bcb35c4cb668ad20f"
integrity sha512-zY1JduE4B3q0k2ZCE+DAF/1efjTXUsKP+VXRtrt/rJCTgDlUyyryx7aOgYXNc1d8gobys/Lof9P9ze8IyRDn7Q==
"@next/swc-linux-x64-musl@15.1.6":
version "15.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.6.tgz#0b8ba80a53e65bf8970ed11ea923001e2512c7cb"
integrity sha512-L4druWmdFSZIIRhF+G60API5sFB7suTbDRhYWSjiw0RbE+15igQvE2g2+S973pMGvwN3guw7cJUjA/TmbPWTHQ==
"@next/swc-linux-x64-musl@15.3.1":
version "15.3.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.1.tgz#639f143bd0f3fd6e1bde4b383dc6cd8a8ff12628"
integrity sha512-FeAbR7FYMWR+Z+M5iSGytVryKHiAsc0x3Nc3J+FD5NVbD5Mqz7fTSy8CYliXinn7T26nDMbpExRUI/4ekTvoiA==
"@next/swc-linux-x64-musl@15.2.0":
version "15.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.2.0.tgz#e23be1d046c9a630a0315588f9d692d9705ac355"
integrity sha512-QqvLZpurBD46RhaVaVBepkVQzh8xtlUN00RlG4Iq1sBheNugamUNPuZEH1r9X1YGQo1KqAe1iiShF0acva3jHQ==
"@next/swc-win32-arm64-msvc@15.1.6":
version "15.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.6.tgz#81b5dbbfdada2c05deef688e799af4a24097b65f"
integrity sha512-s8w6EeqNmi6gdvM19tqKKWbCyOBvXFbndkGHl+c9YrzsLARRdCHsD9S1fMj8gsXm9v8vhC8s3N8rjuC/XrtkEg==
"@next/swc-win32-arm64-msvc@15.3.1":
version "15.3.1"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.1.tgz#52ee1e63b192fec8f0230caf839cfc308d0d44d1"
integrity sha512-yP7FueWjphQEPpJQ2oKmshk/ppOt+0/bB8JC8svPUZNy0Pi3KbPx2Llkzv1p8CoQa+D2wknINlJpHf3vtChVBw==
"@next/swc-win32-arm64-msvc@15.2.0":
version "15.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.2.0.tgz#9e2cb008b82c676dad7d632a43549f969cb2194f"
integrity sha512-ODZ0r9WMyylTHAN6pLtvUtQlGXBL9voljv6ujSlcsjOxhtXPI1Ag6AhZK0SE8hEpR1374WZZ5w33ChpJd5fsjw==
"@next/swc-win32-x64-msvc@15.1.6":
version "15.1.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.6.tgz#131993c45ffd124fb4b15258e2f3f9669c143e3c"
integrity sha512-6xomMuu54FAFxttYr5PJbEfu96godcxBTRk1OhAvJq0/EnmFU/Ybiax30Snis4vdWZ9LGpf7Roy5fSs7v/5ROQ==
"@next/swc-win32-x64-msvc@15.3.1":
version "15.3.1"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.1.tgz#df5ceb9c3b97bf0d61cb6e84f79bbf9e91a89d29"
integrity sha512-3PMvF2zRJAifcRNni9uMk/gulWfWS+qVI/pagd+4yLF5bcXPZPPH2xlYRYOsUjmCJOXSTAC2PjRzbhsRzR2fDQ==
"@next/swc-win32-x64-msvc@15.2.0":
version "15.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.2.0.tgz#d280f450a5b6dbb7437c3265f81ea62febf4bf3c"
integrity sha512-8+4Z3Z7xa13NdUuUAcpVNA6o76lNPniBd9Xbo02bwXQXnZgFvEopwY2at5+z7yHl47X9qbZpvwatZ2BRo3EdZw==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@ -4033,10 +3915,10 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb"
integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==
"@types/react-dom@19.0.4", "@types/react-dom@^19":
version "19.0.4"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.0.4.tgz#bedba97f9346bd4c0fe5d39e689713804ec9ac89"
integrity sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==
"@types/react-dom@^19", "@types/react-dom@^19.0.3":
version "19.1.2"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.1.2.tgz#bd1fe3b8c28a3a2e942f85314dcfb71f531a242f"
integrity sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==
"@types/react-twemoji@^0.4.3":
version "0.4.3"
@ -4045,10 +3927,10 @@
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@19.0.10", "@types/react@^19":
version "19.0.10"
resolved "https://registry.yarnpkg.com/@types/react/-/react-19.0.10.tgz#d0c66dafd862474190fe95ce11a68de69ed2b0eb"
integrity sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==
"@types/react@*", "@types/react@^19", "@types/react@^19.0.8":
version "19.1.2"
resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.2.tgz#11df86f66f188f212c90ecb537327ec68bfd593f"
integrity sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==
dependencies:
csstype "^3.0.2"
@ -10339,12 +10221,12 @@ next@15.1.6:
"@next/swc-win32-x64-msvc" "15.1.6"
sharp "^0.33.5"
next@^15.3.1:
version "15.3.1"
resolved "https://registry.yarnpkg.com/next/-/next-15.3.1.tgz#69cf2c124e504db64e14fc75eb29bd64c0c787a7"
integrity sha512-8+dDV0xNLOgHlyBxP1GwHGVaNXsmp+2NhZEYrXr24GWLHtt27YrBPbPuHvzlhi7kZNYjeJNR93IF5zfFu5UL0g==
next@15.2.0:
version "15.2.0"
resolved "https://registry.yarnpkg.com/next/-/next-15.2.0.tgz#00f4619ae4322102b08c1a8bf315f7b757525508"
integrity sha512-VaiM7sZYX8KIAHBrRGSFytKknkrexNfGb8GlG6e93JqueCspuGte8i4ybn8z4ww1x3f2uzY4YpTaBEW4/hvsoQ==
dependencies:
"@next/env" "15.3.1"
"@next/env" "15.2.0"
"@swc/counter" "0.1.3"
"@swc/helpers" "0.5.15"
busboy "1.6.0"
@ -10352,15 +10234,15 @@ next@^15.3.1:
postcss "8.4.31"
styled-jsx "5.1.6"
optionalDependencies:
"@next/swc-darwin-arm64" "15.3.1"
"@next/swc-darwin-x64" "15.3.1"
"@next/swc-linux-arm64-gnu" "15.3.1"
"@next/swc-linux-arm64-musl" "15.3.1"
"@next/swc-linux-x64-gnu" "15.3.1"
"@next/swc-linux-x64-musl" "15.3.1"
"@next/swc-win32-arm64-msvc" "15.3.1"
"@next/swc-win32-x64-msvc" "15.3.1"
sharp "^0.34.1"
"@next/swc-darwin-arm64" "15.2.0"
"@next/swc-darwin-x64" "15.2.0"
"@next/swc-linux-arm64-gnu" "15.2.0"
"@next/swc-linux-arm64-musl" "15.2.0"
"@next/swc-linux-x64-gnu" "15.2.0"
"@next/swc-linux-x64-musl" "15.2.0"
"@next/swc-win32-arm64-msvc" "15.2.0"
"@next/swc-win32-x64-msvc" "15.2.0"
sharp "^0.33.5"
nextjs-toploader@^1.6.12:
version "1.6.12"
@ -11160,7 +11042,14 @@ react-day-picker@8.10.1:
resolved "https://registry.yarnpkg.com/react-day-picker/-/react-day-picker-8.10.1.tgz#4762ec298865919b93ec09ba69621580835b8e80"
integrity sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==
react-dom@^19.0.0, react-dom@^19.1.0:
react-dom@19.0.0:
version "19.0.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0.tgz#43446f1f01c65a4cd7f7588083e686a6726cfb57"
integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==
dependencies:
scheduler "^0.25.0"
react-dom@^19.0.0:
version "19.1.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.1.0.tgz#133558deca37fa1d682708df8904b25186793623"
integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==
@ -11333,7 +11222,12 @@ react-transition-group@^4.4.5:
loose-envify "^1.4.0"
prop-types "^15.6.2"
react@^19.0.0, react@^19.1.0:
react@19.0.0:
version "19.0.0"
resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd"
integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==
react@^19.0.0:
version "19.1.0"
resolved "https://registry.yarnpkg.com/react/-/react-19.1.0.tgz#926864b6c48da7627f004795d6cce50e90793b75"
integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==
@ -11914,6 +11808,11 @@ sax@>=0.6.0:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f"
integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==
scheduler@^0.25.0:
version "0.25.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015"
integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==
scheduler@^0.26.0:
version "0.26.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.26.0.tgz#4ce8a8c2a2095f13ea11bf9a445be50c555d6337"
@ -12048,36 +11947,6 @@ sharp@^0.33.1, sharp@^0.33.5:
"@img/sharp-win32-ia32" "0.33.5"
"@img/sharp-win32-x64" "0.33.5"
sharp@^0.34.1:
version "0.34.1"
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.34.1.tgz#e5922894b0cc7ddf159eeabc6d5668e4e8b11d61"
integrity sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==
dependencies:
color "^4.2.3"
detect-libc "^2.0.3"
semver "^7.7.1"
optionalDependencies:
"@img/sharp-darwin-arm64" "0.34.1"
"@img/sharp-darwin-x64" "0.34.1"
"@img/sharp-libvips-darwin-arm64" "1.1.0"
"@img/sharp-libvips-darwin-x64" "1.1.0"
"@img/sharp-libvips-linux-arm" "1.1.0"
"@img/sharp-libvips-linux-arm64" "1.1.0"
"@img/sharp-libvips-linux-ppc64" "1.1.0"
"@img/sharp-libvips-linux-s390x" "1.1.0"
"@img/sharp-libvips-linux-x64" "1.1.0"
"@img/sharp-libvips-linuxmusl-arm64" "1.1.0"
"@img/sharp-libvips-linuxmusl-x64" "1.1.0"
"@img/sharp-linux-arm" "0.34.1"
"@img/sharp-linux-arm64" "0.34.1"
"@img/sharp-linux-s390x" "0.34.1"
"@img/sharp-linux-x64" "0.34.1"
"@img/sharp-linuxmusl-arm64" "0.34.1"
"@img/sharp-linuxmusl-x64" "0.34.1"
"@img/sharp-wasm32" "0.34.1"
"@img/sharp-win32-ia32" "0.34.1"
"@img/sharp-win32-x64" "0.34.1"
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"