implement mods functionality and add meta data #3

Closed
NerfedJabolo wants to merge 10 commits from main into main
27 changed files with 718 additions and 174 deletions

5
.env Normal file
View file

@ -0,0 +1,5 @@
ADMIN_USERNAME=
ADMIN_PASSWORD=
MONGODB_URI=
UPLOADTHING_SECRET=
UPLOADTHING_APP_ID=

3
.gitignore vendored
View file

@ -34,3 +34,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
#bun
bun.lockb

13
actions/login.actions.ts Normal file
View file

@ -0,0 +1,13 @@
'use server';
import { NextApiRequest } from 'next';
import { NextResponse } from 'next/server';
export async function POST(req: NextApiRequest) {
const { username, password } = await req.body;
if (username === process.env.USERNAME && password === process.env.PASSWORD) {
return NextResponse.json({ success: true });
} else {
return NextResponse.json({ success: false });
}
}

View file

@ -0,0 +1,123 @@
'use client';
import React from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { UploadButton, UploadDropzone } from '@/lib/uploadthing';
import { logsSchema } from '@/lib/validations/validation';
const AdminPage = () => {
const form = useForm<z.infer<typeof logsSchema>>({
resolver: zodResolver(logsSchema),
});
const onSubmit: SubmitHandler<z.infer<typeof logsSchema>> = async (data) => {
const response = await fetch('/api/uploadlogs', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (response.ok) {
form.reset();
console.log('Upload successful');
alert('Uploaded');
} else {
console.error('Upload failed');
alert('Upload Failed');
}
};
return (
<section id="admin-page" className="wrapper container">
<h1 className="text-3xl font-bold py-6">Admin Upload Section</h1>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="fileName"
render={({ field }) => (
<FormItem>
<FormLabel>File Name</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="version"
render={({ field }) => (
<FormItem>
<FormLabel>Version</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="downloadLink"
render={({ field }) => (
<FormItem>
<FormLabel>Download Link</FormLabel>
<UploadButton
endpoint="imageUploader"
onClientUploadComplete={(res) => {
field.onChange(res[0].url);
}}
onUploadError={(error: Error) => {
alert(`ERROR! ${error.message}`);
}}
/>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="fileSize"
render={({ field }) => (
<FormItem>
<FormLabel>File Size</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
className="w-full text-lg rounded-full"
size={'lg'}
>
Submit
</Button>
</form>
</Form>
</section>
);
};
export default AdminPage;

View file

@ -0,0 +1,123 @@
'use client';
import React from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { UploadButton, UploadDropzone } from '@/lib/uploadthing';
import { modsSchema } from '@/lib/validations/validation';
const AdminPage = () => {
const form = useForm<z.infer<typeof modsSchema>>({
resolver: zodResolver(modsSchema),
});
const onSubmit: SubmitHandler<z.infer<typeof modsSchema>> = async (data) => {
const response = await fetch('/api/uploadmods', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (response.ok) {
form.reset();
console.log('Upload successful');
alert('Uploaded');
} else {
console.error('Upload failed');
alert('Upload Failed');
}
};
return (
<section id="admin-page" className="wrapper container">
<h1 className="text-3xl font-bold py-6">Admin Upload Section</h1>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="fileName"
render={({ field }) => (
<FormItem>
<FormLabel>File Name</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="version"
render={({ field }) => (
<FormItem>
<FormLabel>Version</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="downloadLink"
render={({ field }) => (
<FormItem>
<FormLabel>Download Link</FormLabel>
<UploadButton
endpoint="imageUploader"
onClientUploadComplete={(res) => {
field.onChange(res[0].url);
}}
onUploadError={(error: Error) => {
alert(`ERROR! ${error.message}`);
}}
/>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="fileSize"
render={({ field }) => (
<FormItem>
<FormLabel>File Size</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
className="w-full text-lg rounded-full"
size={'lg'}
>
Submit
</Button>
</form>
</Form>
</section>
);
};
export default AdminPage;

View file

@ -1,4 +1,9 @@
import React from "react";
import React from 'react';
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Blog - SVRJS',
};
const BlogPage = () => {
return <div>BlogPage</div>;

View file

@ -0,0 +1,105 @@
'use client';
import { useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
import { Download } from 'lucide-react';
import Link from 'next/link';
interface Download {
_id: string;
date: string;
fileName: string;
version: string;
fileSize: string;
downloadLink: string;
}
const DownloadPage: React.FC = () => {
const [downloads, setDownloads] = useState<Download[]>([]);
const [error, setError] = useState('');
const fetchDownloads = async () => {
try {
const response = await fetch('/api/logs', {
method: 'GET',
});
if (response.ok) {
const data: Download[] = await response.json();
setDownloads(data);
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error);
}
};
useEffect(() => {
fetchDownloads();
const interval = setInterval(() => {
fetchDownloads();
}, 10000);
return () => clearInterval(interval);
}, []);
return (
<section
id="download"
className="wrapper container py-24 md:py-28 gap-4 flex flex-col"
>
<h1 className="text-3xl md:text-5xl font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
Downloads
</h1>
<p className="text-lg text-muted-foreground text-start mb-4">
Get all the latest version of SVRJS download and compiled Files here!
</p>
{error && <p className="text-red-500">{error}</p>}
<Table>
<TableCaption>A list of all available downloads.</TableCaption>
<TableHeader>
<TableRow>
<TableHead className="w-[150px]">Date</TableHead>
<TableHead>File Name</TableHead>
<TableHead>Version</TableHead>
<TableHead>File Size</TableHead>
<TableHead className="text-right">Download Link</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{downloads
.slice(0, 10)
.reverse()
.map((download) => (
<TableRow key={download._id}>
<TableCell className="font-medium">{download.date}</TableCell>
<TableCell>{download.fileName}</TableCell>
<TableCell>{download.version}</TableCell>
<TableCell className="text-left">{download.fileSize}</TableCell>
<TableCell className="flex items-center justify-end">
<Link href={download.downloadLink}>
<Button variant={'ghost'} className="">
<Download className="w-4 h-4 mr-2" />
Download
</Button>
</Link>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</section>
);
};
export default DownloadPage;

View file

@ -1,7 +1,15 @@
import React from "react";
import Sidebar from '@/components/shared/Sidebar';
const Docs = () => {
return <div>Docs</div>;
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Docs - SVRJS',
};
export default Docs;
export default function Page() {
return (
<>
<Sidebar />
</>
);
}

View file

@ -0,0 +1,11 @@
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Downloads - SVRJS',
};
const ModLayout = ({ children }: { children: React.ReactNode }) => {
return <main>{children}</main>;
};
export default ModLayout;

View file

@ -10,9 +10,9 @@ import {
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Download } from "lucide-react";
import Link from "next/link";
} from '@/components/ui/table';
import { Download } from 'lucide-react';
import Link from 'next/link';
interface Download {
_id: string;

View file

@ -1,4 +1,9 @@
import React from "react";
import React from 'react';
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Forum - SVRJS',
};
const Forum = () => {
return <div>Forum</div>;

View file

@ -1,16 +1,21 @@
import Footer from "@/components/shared/Footer";
import Navbar from "@/components/shared/Navbar";
import Footer from '@/components/shared/Footer';
import Navbar from '@/components/shared/Navbar';
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Home - SVRJS',
};
export default function PageLayout({
children,
children,
}: {
children: React.ReactNode;
children: React.ReactNode;
}) {
return (
<main className="flex flex-col min-h-screen">
<Navbar />
<div className="flex-grow flex-1">{children}</div>
<Footer />
</main>
);
return (
<main className="flex flex-col min-h-screen">
<Navbar />
<div className="flex-grow flex-1">{children}</div>
<Footer />
</main>
);
}

View file

@ -0,0 +1,11 @@
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'MOD - SVRJS',
};
const ModLayout = ({ children }: { children: React.ReactNode }) => {
return <main>{children}</main>;
};
export default ModLayout;

View file

@ -1,4 +1,7 @@
import { Button } from "@/components/ui/button";
'use client';
import { useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
import {
Table,
TableBody,
@ -7,53 +10,61 @@ import {
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Download } from "lucide-react";
import Link from "next/link";
} from '@/components/ui/table';
import { Download } from 'lucide-react';
import Link from 'next/link';
const downloads = [
{
date: "2024-06-01",
fileName: "SVRJS_v1.0.0.zip",
version: "1.0.0",
fileSize: "15MB",
downloadLink: "/downloads/SVRJS_v1.0.0.zip",
},
{
date: "2024-06-10",
fileName: "SVRJS_v1.1.0.zip",
version: "1.1.0",
fileSize: "18MB",
downloadLink: "/downloads/SVRJS_v1.1.0.zip",
},
{
date: "2024-06-15",
fileName: "SVRJS_v1.2.0.zip",
version: "1.2.0",
fileSize: "20MB",
downloadLink: "/downloads/SVRJS_v1.2.0.zip",
},
{
date: "2024-06-20",
fileName: "SVRJS_v1.3.0.zip",
version: "1.3.0",
fileSize: "22MB",
downloadLink: "/downloads/SVRJS_v1.3.0.zip",
},
];
interface Download {
_id: string;
date: string;
fileName: string;
version: string;
fileSize: string;
downloadLink: string;
}
const DownloadPage: React.FC = () => {
const [downloads, setDownloads] = useState<Download[]>([]);
const [error, setError] = useState('');
const fetchDownloads = async () => {
try {
const response = await fetch('/api/mods', {
method: 'GET',
});
if (response.ok) {
const data: Download[] = await response.json();
setDownloads(data);
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error);
}
};
useEffect(() => {
fetchDownloads();
const interval = setInterval(() => {
fetchDownloads();
}, 10000);
return () => clearInterval(interval);
}, []);
const Mods = () => {
return (
<section
id="mods"
id="download"
className="wrapper container py-24 md:py-28 gap-4 flex flex-col"
>
<h1 className="text-3xl md:text-5xl font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
SvrJS Mods
Downloads
</h1>
<p className="text-lg text-muted-foreground text-start mb-4">
Get all the latest version of SVRJS Mods and compiled Files here!
Get all the latest version of SVRJS download and compiled Files here!
</p>
{error && <p className="text-red-500">{error}</p>}
<Table>
<TableCaption>A list of all available downloads.</TableCaption>
<TableHeader>
@ -61,31 +72,34 @@ const Mods = () => {
<TableHead className="w-[150px]">Date</TableHead>
<TableHead>File Name</TableHead>
<TableHead>Version</TableHead>
<TableHead>Download Link</TableHead>
<TableHead className="text-right">File Size</TableHead>
<TableHead>File Size</TableHead>
<TableHead className="text-right">Download Link</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{downloads.map((download) => (
<TableRow key={download.fileName}>
<TableCell className="font-medium">{download.date}</TableCell>
<TableCell>{download.fileName}</TableCell>
<TableCell>{download.version}</TableCell>
<TableCell className="text-left">{download.fileSize}</TableCell>
<TableCell className="flex items-center justify-end">
<Link href={download.downloadLink}>
<Button variant={"ghost"} className="">
<Download className="w-4 h-4 mr-2" />
Download
</Button>
</Link>
</TableCell>
</TableRow>
))}
{downloads
.slice(0, 10)
.reverse()
.map((download) => (
<TableRow key={download._id}>
<TableCell className="font-medium">{download.date}</TableCell>
<TableCell>{download.fileName}</TableCell>
<TableCell>{download.version}</TableCell>
<TableCell className="text-left">{download.fileSize}</TableCell>
<TableCell className="flex items-center justify-end">
<Link href={download.downloadLink}>
<Button variant={'ghost'} className="">
<Download className="w-4 h-4 mr-2" />
Download
</Button>
</Link>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</section>
);
};
export default Mods;
export default DownloadPage;

View file

@ -1,10 +1,10 @@
import About from "@/components/shared/About";
import DataTable from "@/components/shared/DataTable";
import Faq from "@/components/shared/FAQ";
import Hero from "@/components/shared/Hero";
import HowItWorks from "@/components/shared/HowItWorks";
import Newsletter from "@/components/shared/Newsletter";
import Partners from "@/components/shared/Partners";
import About from '@/components/shared/About';
import DataTable from '@/components/shared/DataTable';
import Faq from '@/components/shared/FAQ';
import Hero from '@/components/shared/Hero';
import HowItWorks from '@/components/shared/HowItWorks';
import Newsletter from '@/components/shared/Newsletter';
import Partners from '@/components/shared/Partners';
const RootPage = () => {
return (

17
app/api/logs/route.ts Normal file
View file

@ -0,0 +1,17 @@
import { NextRequest, NextResponse } from 'next/server';
import clientPromise from '@/lib/db';
// Handler for GET requests
export async function GET(req: NextRequest) {
try {
const client = await clientPromise;
const db = client.db('downloadsDatabase');
const downloads = await db.collection('logs').find().toArray();
return NextResponse.json(downloads, { status: 200 });
} catch (error) {
return NextResponse.json(
{ error: 'Failed to fetch logs' },
{ status: 500 }
);
}
}

17
app/api/mods/route.ts Normal file
View file

@ -0,0 +1,17 @@
import { NextRequest, NextResponse } from 'next/server';
import clientPromise from '@/lib/db';
// Handler for GET requests
export async function GET(req: NextRequest) {
try {
const client = await clientPromise;
const db = client.db('downloadsDatabase');
const downloads = await db.collection('mods').find().toArray();
return NextResponse.json(downloads, { status: 200 });
} catch (error) {
return NextResponse.json(
{ error: 'Failed to fetch mods' },
{ status: 500 }
);
}
}

View file

View file

@ -0,0 +1,20 @@
import { NextResponse } from 'next/server';
import clientPromise from '@/lib/db';
export async function POST(request: Request) {
const body = await request.json();
const { fileName, version, downloadLink, fileSize } = body;
const client = await clientPromise;
const db = client.db('downloadsDatabase');
const result = await db.collection('logs').insertOne({
date: new Date().toISOString().split('T')[0],
fileName,
version,
downloadLink,
fileSize,
});
return NextResponse.json({ success: true, id: result.insertedId });
}

View file

@ -0,0 +1,20 @@
import { NextResponse } from 'next/server';
import clientPromise from '@/lib/db';
export async function POST(request: Request) {
const body = await request.json();
const { fileName, version, downloadLink, fileSize } = body;
const client = await clientPromise;
const db = client.db('downloadsDatabase');
const result = await db.collection('mods').insertOne({
date: new Date().toISOString().split('T')[0],
fileName,
version,
downloadLink,
fileSize,
});
return NextResponse.json({ success: true, id: result.insertedId });
}

View file

@ -4,13 +4,13 @@ import "./globals.css";
import { ThemeProvider } from "@/components/shared/providers/themeprovider";
const poppins = Poppins({
weight: ["400", "600", "700", "900"],
subsets: ["latin"],
weight: ['400', '600', '700', '900'],
subsets: ['latin'],
});
export const metadata: Metadata = {
title: "SVRJS - A Web Server running on Nodejs",
description: "Open Source Software Library",
title: 'SVRJS - A Web Server running on Nodejs',
description: 'Open Source Software Library',
};
export default function RootLayout({

View file

@ -1,17 +1,17 @@
"use client";
'use client';
import {
NavigationMenu,
NavigationMenuItem,
NavigationMenuList,
} from "@radix-ui/react-navigation-menu";
import Image from "next/image";
import Link from "next/link";
import ThemeToggle from "../ui/theme-toggle";
import { NAVBAR } from "@/constants";
import { buttonVariants } from "../ui/button";
import MobileNav from "./MobileNav";
import { usePathname } from "next/navigation";
} from '@radix-ui/react-navigation-menu';
import Image from 'next/image';
import Link from 'next/link';
import ThemeToggle from '../ui/theme-toggle';
import { NAVBAR } from '@/constants';
import { buttonVariants } from '../ui/button';
import MobileNav from './MobileNav';
import { usePathname } from 'next/navigation';
const Navbar = () => {
const pathname = usePathname();
@ -50,9 +50,9 @@ const Navbar = () => {
href={href}
target={target}
className={`text-[17px] tracking-tight ${
pathname == href ? "bg-accent/40" : ""
pathname == href ? 'bg-accent/40' : ''
} ${buttonVariants({
variant: "ghost",
variant: 'ghost',
})}`}
>
{label}
@ -61,14 +61,14 @@ const Navbar = () => {
</nav>
<div className="hidden md:flex gap-2 items-center">
{NAVBAR.rightLinks?.map(({ href = "", label, target }) => (
{NAVBAR.rightLinks?.map(({ href = '', label, target }) => (
<Link
key={label}
href={href}
target={target}
className={`border ${buttonVariants({
variant: "ghost",
size: "icon",
variant: 'ghost',
size: 'icon',
})}`}
>
<Image

View file

@ -0,0 +1,24 @@
import React from 'react';
const Sidebar = () => {
return (
<div className="w-[250px] h-[100vh] border-r dark:border-r-slate-800 pl-4 pt-2">
<span className="flex flex-col gap-2">
<h2 className="text-2xl font-bold">First use</h2>
<ul className="pl-4 flex flex-col gap-2">
<li>System requirements</li>
<li>Installation</li>
<li>Features</li>
<li>SVR.JS files</li>
<li>SVR.JS utilities</li>
<li>SVR.JS commands</li>
<li>Updating SVR.JS</li>
<li>Common problems</li>
<li>Bun support</li>
</ul>
</span>
</div>
);
};
export default Sidebar;

View file

@ -1,53 +1,53 @@
import { BadgeAlert, BarChart4, Cog, ShieldCheck } from "lucide-react";
import { Download, Home, Settings, User } from "lucide-react";
import { BadgeAlert, BarChart4, Cog, ShieldCheck } from 'lucide-react';
import { Download, Home, Settings, User } from 'lucide-react';
export const NAVBAR = {
centerLinks: [
{
href: "/",
target: "_self",
label: "Home",
href: '/',
target: '_self',
label: 'Home',
},
{
href: "/docs",
target: "_self",
label: "Docs",
href: '/docs',
target: '_self',
label: 'Docs',
},
{
href: "/forum",
target: "_self",
label: "Forum",
href: '/forum',
target: '_self',
label: 'Forum',
},
{
href: "/blog",
target: "_self",
label: "Blog",
href: '/blog',
target: '_self',
label: 'Blog',
},
],
rightLinks: [
{
label: "Git",
target: "_blank",
href: "https://git.svrjs.org/",
label: 'Git',
target: '_blank',
href: 'https://git.svrjs.org/',
},
],
};
export const stats = [
{
title: "Downloads",
title: 'Downloads',
count: 69,
},
{
title: "Users",
title: 'Users',
count: 42,
},
{
title: "Stars",
title: 'Stars',
count: 6,
},
{
title: "Products",
title: 'Products',
count: 2,
},
];
@ -55,121 +55,121 @@ export const stats = [
export const Features = [
{
icon: <ShieldCheck className="w-10 h-10 text-primary" />,
title: "Complete Secured ",
title: 'Completely Secured ',
description:
"lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor",
'lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor',
},
{
icon: <BadgeAlert className="w-10 h-10 text-primary" />,
title: "Best Support",
title: 'Best Support',
description:
"lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor",
'lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor',
},
{
icon: <BarChart4 className="w-10 h-10 text-primary" />,
title: "Most Scalable ",
title: 'Most Scalable ',
description:
"lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor",
'lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor',
},
{
icon: <Cog className="w-10 h-10 text-primary" />,
title: "Fully Configurable ",
title: 'Fully Configurable ',
description:
"lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor",
'lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor',
},
];
export const questions = [
{
key: "item-1",
question: "What is a web server?",
key: 'item-1',
question: 'What is a web server?',
answer:
"A web server is computer software that accepts HTTP requests and serves websites. Web servers can also be underlying hardware running web server software.",
'A web server is computer software that accepts HTTP requests and serves websites. Web servers can also be underlying hardware running web server software.',
},
{
key: "item-2",
question: "What is SVR.JS?",
key: 'item-2',
question: 'What is SVR.JS?',
answer:
"SVR.JS is web server software running on Node.JS that can host both static and dynamic content. With additional mods, SVR.JS can be used for different types of dynamic content and can even be used as a forward or reverse proxy. SVR.JS is licensed under a permissive MIT/X11 license",
'SVR.JS is web server software running on Node.JS that can host both static and dynamic content. With additional mods, SVR.JS can be used for different types of dynamic content and can even be used as a forward or reverse proxy. SVR.JS is licensed under a permissive MIT/X11 license',
},
{
key: "item-3",
question: "How was SVR.JS created?",
key: 'item-3',
question: 'How was SVR.JS created?',
answer:
"Someone in 2018 wanted to create a website, but he didnt know about setting up popular web server software like Apache httpd, NGINX, or IIS... So he created his own web server in Node.JS to serve his website! And he saved it in a file called svr.js. Since then, this web server has been gradually turned from a web server intended for one website into a general-purpose web server, which is what SVR.JS is today!",
'Someone in 2018 wanted to create a website, but he didnt know about setting up popular web server software like Apache httpd, NGINX, or IIS... So he created his own web server in Node.JS to serve his website! And he saved it in a file called svr.js. Since then, this web server has been gradually turned from a web server intended for one website into a general-purpose web server, which is what SVR.JS is today!',
},
{
key: "item-4",
question: "How did SVR.JS get its name?",
key: 'item-4',
question: 'How did SVR.JS get its name?',
answer:
"SVR.JS got its name from the original name of the server script: svr.js, one of many generic file names for a server written in JavaScript.",
'SVR.JS got its name from the original name of the server script: svr.js, one of many generic file names for a server written in JavaScript.',
},
{
key: "item-5",
question: "What is Node.JS?",
key: 'item-5',
question: 'What is Node.JS?',
answer:
"Node.JS is an asynchronous event-driven JavaScript runtime built on Chromiums V8 engine. Node.JS is designed to build scalable network applications.",
'Node.JS is an asynchronous event-driven JavaScript runtime built on Chromiums V8 engine. Node.JS is designed to build scalable network applications.',
},
{
key: "item-6",
question: "How can I use SVR.JS?",
key: 'item-6',
question: 'How can I use SVR.JS?',
answer:
"You can read the documents to learn how to use the SVR.JS web server.",
'You can read the documents to learn how to use the SVR.JS web server.',
},
];
export const FOOTERLINKS = {
otherPages: [
{ href: "/", label: "Home" },
{ href: "/contact", label: "Contact" },
{ href: "/blog", label: "Blog" },
{ href: "/forum", label: "Forum" },
{ href: '/', label: 'Home' },
{ href: '/contact', label: 'Contact' },
{ href: '/blog', label: 'Blog' },
{ href: '/forum', label: 'Forum' },
],
plans: [
{ href: "/docs", label: "Docs" },
{ href: "/downloads", label: "Downloads" },
{ href: "/tos", label: "Terms of Serivce" },
{ href: "/privacy-policy", label: "Privacy Policy" },
{ href: '/docs', label: 'Docs' },
{ href: '/downloads', label: 'Downloads' },
{ href: '/tos', label: 'Terms of Serivce' },
{ href: '/privacy-policy', label: 'Privacy Policy' },
],
social: {
supportText: "Support Us on Socials",
supportText: 'Support Us on Socials',
},
footerBottom: {
designedBy: {
href: "https://abhijee.com",
label: "Proxy",
href: 'https://abhijee.com',
label: 'Proxy',
},
rightsReserved: {
href: "https://cyprostudio.com",
label: "SVRJS",
href: 'https://cyprostudio.com',
label: 'SVRJS',
},
},
};
export const AdminLinks = [
{
name: "Dashboard",
url: "/admin",
name: 'Dashboard',
url: '/admin',
icon: Home,
},
{
name: "Downloads",
url: "/admin/downloads",
name: 'Downloads',
url: '/admin/downloads',
icon: Download,
},
{
name: "Mods",
url: "/admin/mods",
name: 'Mods',
url: '/admin/mods',
icon: User,
},
{
name: "Logs",
url: "/admin/changelogs",
name: 'Logs',
url: '/admin/changelogs',
icon: Settings,
},
{
name: "Back Home",
url: "/",
name: 'Back Home',
url: '/',
icon: Home,
},
];

View file

@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from 'zod';
export const downloadSchema = z.object({
fileName: z.string().nonempty(),
@ -6,3 +6,17 @@ export const downloadSchema = z.object({
downloadLink: z.string().url().nonempty(),
fileSize: z.string().nonempty(),
});
export const modsSchema = z.object({
fileName: z.string().nonempty(),
version: z.string().nonempty(),
downloadLink: z.string().url().nonempty(),
fileSize: z.string().nonempty(),
});
export const logsSchema = z.object({
fileName: z.string().nonempty(),
version: z.string().nonempty(),
downloadLink: z.string().url().nonempty(),
fileSize: z.string().nonempty(),
});

View file

@ -31,6 +31,7 @@
"mongoose": "^8.4.3",
"next": "14.2.3",
"next-themes": "^0.3.0",
"nookies": "^2.5.2",
"react": "^18",
"react-dom": "^18",
"react-fontawesome": "^1.7.1",

View file

@ -21,6 +21,6 @@
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "lib/Hoc/withAuth.jsx"],
"exclude": ["node_modules"]
}