From df13e78af69ad25e2ef4a394f3443d885b5930d5 Mon Sep 17 00:00:00 2001
From: McMistrzYT <56406996+McMistrzYT@users.noreply.github.com>
Date: Sat, 20 Jan 2024 23:34:31 +0100
Subject: [PATCH] sewer
---
Server/.example.env | 8 +
Server/.gitignore | 132 ++++
Server/README.md | 7 +
Server/Source/Handlers/Server.ts | 56 ++
Server/Source/Modules/Classes.ts | 19 +
Server/Source/Modules/Constants.ts | 17 +
Server/Source/Modules/FNUtil.ts | 108 ++++
Server/Source/Modules/FestivalUtil.ts | 35 ++
Server/Source/Modules/Logger.ts | 19 +
Server/Source/Modules/PagesUtil.ts | 13 +
Server/Source/Routes/Admin.ts | 25 +
Server/Source/Routes/Example.ts | 11 +
Server/Source/Routes/Pages.ts | 39 ++
Server/Source/Routes/Root.ts | 9 +
Server/Source/index.ts | 21 +
Server/package-lock.json | 870 ++++++++++++++++++++++++++
Server/package.json | 48 ++
Server/tsconfig.json | 107 ++++
18 files changed, 1544 insertions(+)
create mode 100644 Server/.example.env
create mode 100644 Server/.gitignore
create mode 100644 Server/README.md
create mode 100644 Server/Source/Handlers/Server.ts
create mode 100644 Server/Source/Modules/Classes.ts
create mode 100644 Server/Source/Modules/Constants.ts
create mode 100644 Server/Source/Modules/FNUtil.ts
create mode 100644 Server/Source/Modules/FestivalUtil.ts
create mode 100644 Server/Source/Modules/Logger.ts
create mode 100644 Server/Source/Modules/PagesUtil.ts
create mode 100644 Server/Source/Routes/Admin.ts
create mode 100644 Server/Source/Routes/Example.ts
create mode 100644 Server/Source/Routes/Pages.ts
create mode 100644 Server/Source/Routes/Root.ts
create mode 100644 Server/Source/index.ts
create mode 100644 Server/package-lock.json
create mode 100644 Server/package.json
create mode 100644 Server/tsconfig.json
diff --git a/Server/.example.env b/Server/.example.env
new file mode 100644
index 0000000..4135f07
--- /dev/null
+++ b/Server/.example.env
@@ -0,0 +1,8 @@
+PORT=6677
+BODY_SIZE_LIMIT=50mb
+PROJECT_NAME=Partypack Service
+SERVER_URL=localhost
+DASHBOARD_URL=localhost:5173 # set this to wherever you're hosting the Partypack dashboard
+ENVIRONMENT=dev
+COOKIE_SIGN_KEY=
+USE_HTTPS=true # set this to false if you're debugging on your computer
\ No newline at end of file
diff --git a/Server/.gitignore b/Server/.gitignore
new file mode 100644
index 0000000..869fbcf
--- /dev/null
+++ b/Server/.gitignore
@@ -0,0 +1,132 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+web_modules/
+
+# TypeScript cache
+*.tsbuildinfo
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional stylelint cache
+.stylelintcache
+
+# Microbundle cache
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variable files
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+.parcel-cache
+
+# Next.js build output
+.next
+out
+
+# Nuxt.js build / generate output
+.nuxt
+dist
+
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and not Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
+
+# vuepress build output
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+.temp
+.cache
+
+# Docusaurus cache and generated files
+.docusaurus
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TernJS port file
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
+
+# yarn v2
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
+
+bin/
\ No newline at end of file
diff --git a/Server/README.md b/Server/README.md
new file mode 100644
index 0000000..6d099cb
--- /dev/null
+++ b/Server/README.md
@@ -0,0 +1,7 @@
+# BasedServer - mc's server base
+Hey! Welcome back to mc's yearly repo dump! Today, I'm making my SERVER BASE public for everyone to use. \
+This template gets rid of the need to write all the boilerplate server code, with an example route included:
+
+![firefox_xQtTduHfDq](https://github.com/McMistrzYT/BasedServer/assets/56406996/3470b5d7-ca06-4aa2-89a6-d57367420e8d)
+
+Have fun, 'cause you aren't getting any help!
diff --git a/Server/Source/Handlers/Server.ts b/Server/Source/Handlers/Server.ts
new file mode 100644
index 0000000..059e634
--- /dev/null
+++ b/Server/Source/Handlers/Server.ts
@@ -0,0 +1,56 @@
+import e from "express"
+import fs from "fs";
+import { BODY_SIZE_LIMIT, COOKIE_SIGN_KEY, DASHBOARD_ROOT, ENDPOINT_AUTHENTICATION_ENABLED, ENDPOINT_AUTH_HEADER, ENDPOINT_AUTH_VALUE, IS_DEBUG, PORT, PROJECT_NAME, SERVER_URL } from "../Modules/Constants";
+import { Msg, Warn } from "../Modules/Logger";
+import { italic, magenta, red, yellow } from "colorette";
+import cookieParser from "cookie-parser";
+import path from "path";
+import cors from "cors";
+
+export const App = e()
+ .disable("etag")
+ .disable("x-powered-by")
+ .use(cookieParser(COOKIE_SIGN_KEY))
+ .use(cors({
+ origin: DASHBOARD_ROOT,
+ credentials: true
+ }))
+ .use(e.json({ limit: BODY_SIZE_LIMIT }))
+ .use(e.urlencoded({ limit: BODY_SIZE_LIMIT, extended: false }));
+
+async function Initialize() {
+ const Files = fs
+ .readdirSync(path.join(".", Symbol.for("ts-node.register.instance") in process ? "Source" : "bin", "Routes"))
+ .filter((F) => F.endsWith(".js") || F.endsWith(".ts"));
+
+ if (ENDPOINT_AUTHENTICATION_ENABLED)
+ Warn(`Endpoint authentication requirement is enabled! You will not be able to connect to the server without the ${yellow(ENDPOINT_AUTH_HEADER as string)} header.`)
+
+ App.use((req, res, next) => {
+ if (ENDPOINT_AUTHENTICATION_ENABLED && req.header(ENDPOINT_AUTH_HEADER as string) !== ENDPOINT_AUTH_VALUE)
+ return res.status(403).send(`${SERVER_URL} is currently locked behind authentication. Come back later!`);
+
+ next();
+ })
+
+ for (const File of Files) {
+ const Contents = await import(path.join("..", "Routes", File));
+ if (!Contents.default) continue;
+ if (!Contents.default.App) continue;
+ App.use(Contents.default.DefaultAPI || "/", Contents.default.App);
+
+ Msg(`Loaded route ${italic(File)}!`);
+ }
+
+ App.listen(PORT, () => Msg(`${magenta(PROJECT_NAME)} now up on port ${magenta(PORT)} ${(IS_DEBUG ? red("(debug environment)") : "")}`));
+}
+
+Initialize();
+
+// ! FESTIVAL-SPECIFIC STUFF
+// set up both utils for usage
+import { LoadSongs } from "../Modules/FestivalUtil";
+import { CacheFortnitePages } from "../Modules/PagesUtil";
+
+LoadSongs();
+CacheFortnitePages();
\ No newline at end of file
diff --git a/Server/Source/Modules/Classes.ts b/Server/Source/Modules/Classes.ts
new file mode 100644
index 0000000..981b336
--- /dev/null
+++ b/Server/Source/Modules/Classes.ts
@@ -0,0 +1,19 @@
+export interface SongItemDefinition {
+ UUID: string,
+ Name: string,
+ Directory?: string,
+ PreviewTime?: number,
+ Year?: number,
+ Artist?: string,
+ Length?: number,
+ MinorMajor: string,
+ Key: string,
+ Album: string,
+ BeatsPerMinute: number,
+ Cover?: string,
+ AssetID: string,
+ Midi?: string,
+ LipsyncData: string,
+ JoinCode: string,
+ GuitarType: string
+}
\ No newline at end of file
diff --git a/Server/Source/Modules/Constants.ts b/Server/Source/Modules/Constants.ts
new file mode 100644
index 0000000..eaea745
--- /dev/null
+++ b/Server/Source/Modules/Constants.ts
@@ -0,0 +1,17 @@
+export const PROJECT_NAME = process.env.PROJECT_NAME ?? "BasedServer"; // Default prefix for the logger module.
+export const BODY_SIZE_LIMIT = process.env.BODY_SIZE_LIMIT ?? "10mb"; // Doesn't accept requests with body sizes larger than this value.
+export const SERVER_URL = process.env.SERVER_URL ?? "localhost"; // The server's URL. Not used for a lot by default.
+export const DASHBOARD_URL = process.env.DASHBOARD_URL ?? "localhost:5173"; // The server's URL. Not used for a lot by default.
+export const PORT = process.env.PORT ?? 80; // Port for the server to run on.
+export const ENDPOINT_AUTHENTICATION_ENABLED = !!process.env.ENDPOINT_AUTHENTICATION; // Whether the server is locked down behind a header.
+export const _ENDPOINT_AUTHENTICATION_ENV = process.env.ENDPOINT_AUTHENTICATION;
+export const ENDPOINT_AUTH_HEADER = _ENDPOINT_AUTHENTICATION_ENV?.split(":")[0]; // Header name for endpoint auth.
+export const ENDPOINT_AUTH_VALUE = _ENDPOINT_AUTHENTICATION_ENV?.split(":")[1]; // Value of the header for endpoint auth.
+export const USE_HTTPS = false;//Boolean(process.env.USE_HTTPS); // todo: fix this shit
+export const DASHBOARD_ROOT = `http${USE_HTTPS ? "s" : ""}://${DASHBOARD_URL}`; // A shortcut so that you don't need to type this out every time you wanna display the dashboard URL.
+export const FULL_SERVER_ROOT = `http${USE_HTTPS ? "s" : ""}://${SERVER_URL}:${PORT}`; // A shortcut so that you don't need to type this out every time you wanna display the server URL.
+export const COOKIE_SIGN_KEY = process.env.COOKIE_SIGN_KEY; // Secret that will be used to sign cookies.
+export const ADMIN_KEY = process.env.ADMIN_KEY; // Secret that will be required to sign into the Admin Dashboard.
+
+export const ENVIRONMENT = process.env.ENVIRONMENT ?? "dev";
+export const IS_DEBUG = ENVIRONMENT.toLowerCase() === "dev" || ENVIRONMENT.toLowerCase() === "stage"; // IS_DEBUG can be used to enable test endpoints, unsafe code and more.
\ No newline at end of file
diff --git a/Server/Source/Modules/FNUtil.ts b/Server/Source/Modules/FNUtil.ts
new file mode 100644
index 0000000..62659b2
--- /dev/null
+++ b/Server/Source/Modules/FNUtil.ts
@@ -0,0 +1,108 @@
+import axios from "axios";
+import { Err } from "./Logger";
+import { red } from "colorette";
+import { FULL_SERVER_ROOT } from "./Constants";
+import { AvailableFestivalSongs } from "./FestivalUtil";
+
+export let FullFortnitePages: object | null = null;
+let LastContentDownloadDate: Date = new Date(0); // set it to 1970 as default cuz im not boutta check if its null
+
+export async function GenerateFortnitePages(): Promise<{ Success: boolean, FNPages: { [key: string]: unknown } | null }> {
+ const { status, data } = // check if 30 minutes have passed since last content update. if so, get a new copy of pages, if not, fuck off
+ FullFortnitePages === null || Date.now() > LastContentDownloadDate.getTime() + 30 * 60 * 1000 ?
+ await axios.get("https://fortnitecontent-website-prod07.ol.epicgames.com/content/api/pages/fortnite-game") :
+ { status: 200, data: FullFortnitePages };
+
+ FullFortnitePages = data;
+ LastContentDownloadDate = new Date();
+
+ if (status !== 200) {
+ Err(`Failed to get Fortnite pages: ${red(status)}`);
+ console.log(data);
+ process.exit(-1); // very big fuck moment, we literally cannot run the server without fortnitepages
+ }
+
+ const AllSongs: { [key: string]: unknown } = {}; // too lazy to actually write a schema for this :D
+ for (const Song of AvailableFestivalSongs)
+ {
+ AllSongs[Song.UUID] = {
+ _title: Song.UUID,
+ _noIndex: false,
+ _activeDate: "2023-01-01T01:00:00.000Z",
+ _locale: "en-US",
+ _templateName: "track",
+ lastModified: new Date().toISOString(),
+ track: {
+ tt: Song.Name, // tt - Title,
+ an: Song.Artist, // an - Artist Name
+ mm: Song.MinorMajor, // mm - Minor, Major
+ mk: Song.Key, // mk - Music Key
+ ab: Song.Album, // ab - Album
+ su: Song.UUID, // su - Song UUID
+ ry: Song.Year, // ry - Release Year
+ mt: Song.BeatsPerMinute, // mt - Music Timing (?)
+ au: Song.Cover ?? `${FULL_SERVER_ROOT}/song/download/${Song.UUID}/cover.png`, // au - Album Cover
+ gt: [ "Jam-LoopIsUnpitched-Beat" ], // gt - Gameplay Tags (but in a different format: Example.Gameplay.Tag -> Example-Gameplay-Tag)
+ ti: `SparksSong:${Song.AssetID.toLowerCase()}`,
+ mu: Song.Midi ?? `${FULL_SERVER_ROOT}/song/download/${Song.UUID}/midi.mid`, // mu - Song Midi (if ending with .mid, decrypted, if with .dat, encrypted)
+ dn: Song.Length, // dn - Track Length (in seconds)
+ ge: [ "Pop" ], // ge - Genres
+ in: { // TODO: fuck with this to make difficulties :+1:
+ ba: 1,
+ pb: 2,
+ pd: 3,
+ pg: 4,
+ vl: 3,
+ ds: 2,
+ gr: 1,
+ _type: "SparkTrackIntensities"
+ }, // in - Intensities (those white bars you see)
+ sib: "Bass", // sib - Bass ID to use (only Bass possible)
+ sid: "Drum", // sid - Drums ID to use (only Drum possible)
+ sig: Song.GuitarType, // sig - Guitar ID to use (Keytar/Guitar)
+ siv: "Vocals", // siv - Vocals ID to use (only Vocals possible)
+ qi: JSON.stringify({ // qi - Query Information (frontend related display stuff and language vocals channel related stuff)
+ sid: Song.UUID, // sid - Song UUID
+ pid: Song.UUID, // pid - Playlist Asset ID
+ title: Song.UUID, // title - Song Name - same as _title
+ tracks: [
+ {
+ part: "ds", // Drum Set
+ channels: [ "FL", "FR" ],
+ vols: [ 4, 4 ]
+ },
+ {
+ part: "bs", // Bass Set (not bullshit)
+ channels: [ "FL", "FR" ],
+ vols: [ 4, 4 ]
+ },
+ {
+ part: "gs", // Guitar Set
+ channels: [ "FL", "FR" ],
+ vols: [ 4, 4 ]
+ },
+ {
+ part: "vs", // Vocal Set (not Visual Studio)
+ channels: [ "FL", "FR" ],
+ vols: [ 4, 4 ]
+ },
+ {
+ part: "fs", // Fart Set (jk i have no idea) (might be Flare Set??????????????)
+ channels: [ "FL", "FR" ],
+ vols: [ 4, 4 ]
+ }
+ ],
+ preview: {
+ starttime: Song.PreviewTime
+ }
+ }),
+ ld: Song.LipsyncData, // ld - Lipsync Data (it's literally a uasset)
+ jc: Song.JoinCode, // jc - Join Code (UEFN empty island with nothing - possibly downloads assets)
+ sn: Song.UUID, // sn - Song Name - same as _title
+ _type: "SparkTrack"
+ }
+ };
+ }
+
+ return { Success: true, FNPages: AllSongs };
+}
\ No newline at end of file
diff --git a/Server/Source/Modules/FestivalUtil.ts b/Server/Source/Modules/FestivalUtil.ts
new file mode 100644
index 0000000..89426dc
--- /dev/null
+++ b/Server/Source/Modules/FestivalUtil.ts
@@ -0,0 +1,35 @@
+import { existsSync, lstatSync, readFileSync, readdirSync } from "fs";
+import { SongItemDefinition } from "./Classes";
+import { CacheFortnitePages } from "./PagesUtil";
+import { Debug, Err, Warn } from "./Logger";
+import { magenta, yellow } from "colorette";
+import watch from "node-watch";
+
+export let AvailableFestivalSongs: SongItemDefinition[] = [];
+
+export function LoadSongs() {
+ AvailableFestivalSongs =
+ readdirSync("../Saved/Songs")
+ .filter(f => lstatSync(`../Saved/Songs/${f}`).isDirectory() && existsSync(`../Saved/Songs/${f}/Config.json`))
+ .map(f => {
+ let Config: SongItemDefinition;
+
+ try { Config = JSON.parse(readFileSync(`../Saved/Songs/${f}/Config.json`).toString()); }
+ catch { Err(`Config for song ${f} failed to parse. Please make sure it's valid!`); process.exit(-1); }
+
+ // todo: validate if it has all the required properities
+ Debug(`Added ${magenta(`${Config.Artist} - ${Config.Name} (${Config.UUID})`)} to the list of available Festival songs!`);
+
+ return {
+ Directory: `../Saved/Songs/${f}`,
+ ...Config
+ };
+ });
+}
+
+watch("../Saved/Songs", { recursive: true }, (Event, Filename) => {
+ Warn(`Detected ${yellow("saved songs")} changes in ${yellow(Filename)}. Reloading available songs!`);
+ Debug(`${magenta(Event)} on ${magenta(Filename)}`);
+ LoadSongs();
+ CacheFortnitePages();
+})
\ No newline at end of file
diff --git a/Server/Source/Modules/Logger.ts b/Server/Source/Modules/Logger.ts
new file mode 100644
index 0000000..59eb3b5
--- /dev/null
+++ b/Server/Source/Modules/Logger.ts
@@ -0,0 +1,19 @@
+import { green, gray, red, magenta, yellow } from "colorette";
+import { IS_DEBUG, PROJECT_NAME } from "./Constants";
+
+export function Msg(Content: string, Prefix = PROJECT_NAME) {
+ console.log(`${gray(new Date().toISOString())} [${green(Prefix)}] ${Content}`);
+}
+
+export function Err(Content: string, Prefix = PROJECT_NAME) {
+ console.log(`${gray(new Date().toISOString())} [${red("ERROR | " + Prefix)}] ${Content}`);
+}
+
+export function Warn(Content: string, Prefix = PROJECT_NAME) {
+ console.log(`${gray(new Date().toISOString())} [${yellow("WARNING | " + Prefix)}] ${Content}`);
+}
+
+export function Debug(Content: string, Prefix = PROJECT_NAME) {
+ if (!IS_DEBUG) return;
+ console.log(`${gray(new Date().toISOString())} [${magenta("DEBUG | " + Prefix)}] ${Content}`);
+}
diff --git a/Server/Source/Modules/PagesUtil.ts b/Server/Source/Modules/PagesUtil.ts
new file mode 100644
index 0000000..1cd793c
--- /dev/null
+++ b/Server/Source/Modules/PagesUtil.ts
@@ -0,0 +1,13 @@
+import { GenerateFortnitePages } from "../Modules/FNUtil";
+import { Msg } from "../Modules/Logger";
+
+export let CachedSongFortnitePages: { [key: string]: unknown } | null = null;
+
+export async function CacheFortnitePages() {
+ const Result = await GenerateFortnitePages();
+ if (!Result.Success)
+ return; // fuck we're fucked
+
+ CachedSongFortnitePages = Result.FNPages;
+ Msg("Successfully reloaded Fortnite pages!");
+}
\ No newline at end of file
diff --git a/Server/Source/Routes/Admin.ts b/Server/Source/Routes/Admin.ts
new file mode 100644
index 0000000..4e06364
--- /dev/null
+++ b/Server/Source/Routes/Admin.ts
@@ -0,0 +1,25 @@
+import { Router } from "express";
+import { ADMIN_KEY } from "../Modules/Constants";
+
+const App = Router();
+
+// ! ANY ENDPOINTS DEFINED IN THIS FILE WILL REQUIRE ADMIN AUTHORIZATION !
+// ! ANY ENDPOINTS DEFINED IN THIS FILE WILL REQUIRE ADMIN AUTHORIZATION !
+// ! ANY ENDPOINTS DEFINED IN THIS FILE WILL REQUIRE ADMIN AUTHORIZATION !
+
+App.use((req, res, next) => {
+ if (req.path === "/key")
+ return res.status(req.body.Key === ADMIN_KEY ? 200 : 403).send(req.body.Key === ADMIN_KEY ? "Login successful!" : "Key doesn't match. Try again.");
+
+ if (req.cookies["AdminKey"] !== ADMIN_KEY)
+ return res.status(403).send("You don't have permission to access this endpoint.");
+
+ next();
+});
+
+App.get("/test", (_, res) => res.send("Permission check OK"));
+
+export default {
+ App,
+ DefaultAPI: "/admin/api"
+}
\ No newline at end of file
diff --git a/Server/Source/Routes/Example.ts b/Server/Source/Routes/Example.ts
new file mode 100644
index 0000000..533cf10
--- /dev/null
+++ b/Server/Source/Routes/Example.ts
@@ -0,0 +1,11 @@
+import { Router } from "express";
+
+const App = Router();
+
+App.get("/", (_, res) => res.send("This content should be served on /welcome!
Go to sub-page"))
+App.get("/sub", (_, res) => res.send("Welcome to the sub-page! This content should be served on /welcome/sub!
Go back"))
+
+export default {
+ App,
+ DefaultAPI: "/welcome"
+}
\ No newline at end of file
diff --git a/Server/Source/Routes/Pages.ts b/Server/Source/Routes/Pages.ts
new file mode 100644
index 0000000..7f28c65
--- /dev/null
+++ b/Server/Source/Routes/Pages.ts
@@ -0,0 +1,39 @@
+import { Router } from "express";
+import { CachedSongFortnitePages } from "../Modules/PagesUtil"; // make sure to import pagesutil after festivalutil :fire:
+import { FullFortnitePages } from "../Modules/FNUtil";
+import axios from "axios";
+import { IS_DEBUG } from "../Modules/Constants";
+
+const App = Router();
+
+App.get("/content/api/pages/fortnite-game", (_, res) => res.json(FullFortnitePages))
+
+App.get("/content/api/pages/fortnite-game/:Section", async (req, res) => {
+ if (req.params.Section.toLowerCase() === "spark-tracks") // custom song injection
+ return res.json(
+ {
+ _title: "spark-tracks",
+ _noIndex: false,
+ _activeDate: "1987-01-01T01:00:00.000Z", // was that the bite of '87
+ lastModified: new Date().toISOString(),
+ _locale: "en-US",
+ _templateName: "blank",
+ ...CachedSongFortnitePages,
+ _suggestedPrefetch: []
+ }
+ );
+
+ const CachedSection = Object.values(FullFortnitePages!).find(x => x._title === req.params.Section);
+ if (!CachedSection)
+ return res.status(404).json({ error: "funny section not found haha kill me" });
+
+ const ContentFromServer = await axios.get(`https://fortnitecontent-website-prod07.ol.epicgames.com/content/api/pages/fortnite-game/${CachedSection._title}`);
+ if (ContentFromServer.status !== 200)
+ return res.status(404).json({ error: IS_DEBUG ? ContentFromServer.data : "Fortnite server returned an error." });
+
+ res.json(ContentFromServer.data);
+})
+
+export default {
+ App
+}
\ No newline at end of file
diff --git a/Server/Source/Routes/Root.ts b/Server/Source/Routes/Root.ts
new file mode 100644
index 0000000..a0b82ac
--- /dev/null
+++ b/Server/Source/Routes/Root.ts
@@ -0,0 +1,9 @@
+import { Router } from "express";
+
+const App = Router();
+
+App.get("/", (_, res) => res.send("Welcome to the root page.
Log in"))
+
+export default {
+ App
+}
\ No newline at end of file
diff --git a/Server/Source/index.ts b/Server/Source/index.ts
new file mode 100644
index 0000000..914559f
--- /dev/null
+++ b/Server/Source/index.ts
@@ -0,0 +1,21 @@
+import { config } from "dotenv";
+config();
+
+import "./Handlers/Server";
+
+/*
+ Welcome to Mc's BasedServer template! (v1.1 - 30.12.2023 update)
+ This is the exact same base I use for projects like Dispriv, Birdnest, GDTS and more.
+
+ Here's a quick overview:
+ - Handlers:
+ Handlers are the big boys - websockets, servers, anything that has to be constantly running.
+ Personally, I always import those here in index, like the Server handler.
+ - Modules:
+ These are smaller, util classes. A good example of that is the Logger util, which lets you
+ print to the console with COLORS!
+ - Routes:
+ The routes folder houses scripts with a router, some endpoints and other fun stuff!
+
+ I recommend familiarizing yourself with all the code before adding anything yourself.
+*/
\ No newline at end of file
diff --git a/Server/package-lock.json b/Server/package-lock.json
new file mode 100644
index 0000000..fed8ffb
--- /dev/null
+++ b/Server/package-lock.json
@@ -0,0 +1,870 @@
+{
+ "name": "basedserver",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "basedserver",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "@types/cors": "^2.8.17",
+ "axios": "^1.6.5",
+ "colorette": "^2.0.20",
+ "cookie-parser": "^1.4.6",
+ "cors": "^2.8.5",
+ "dotenv": "^16.3.1",
+ "express": "^4.18.2"
+ },
+ "devDependencies": {
+ "@types/cookie-parser": "^1.4.6",
+ "@types/express": "^4.17.18",
+ "@types/node": "^20.6.3",
+ "tslib": "^2.6.2",
+ "typescript": "^5.2.2"
+ }
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.3",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz",
+ "integrity": "sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.36",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz",
+ "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/cookie-parser": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.6.tgz",
+ "integrity": "sha512-KoooCrD56qlLskXPLGUiJxOMnv5l/8m7cQD2OxJ73NPMhuSz9PmvwRD6EpjDyKBVrdJDdQ4bQK7JFNHnNmax0w==",
+ "dev": true,
+ "dependencies": {
+ "@types/express": "*"
+ }
+ },
+ "node_modules/@types/cors": {
+ "version": "2.8.17",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
+ "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.18",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.18.tgz",
+ "integrity": "sha512-Sxv8BSLLgsBYmcnGdGjjEjqET2U+AKAdCRODmMiq02FgjwuV75Ut85DRpvFjyw/Mk0vgUOliGRU0UUmuuZHByQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.33",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "4.17.37",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.37.tgz",
+ "integrity": "sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.2.tgz",
+ "integrity": "sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==",
+ "dev": true
+ },
+ "node_modules/@types/mime": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz",
+ "integrity": "sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "20.8.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz",
+ "integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w=="
+ },
+ "node_modules/@types/qs": {
+ "version": "6.9.8",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz",
+ "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==",
+ "dev": true
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.5.tgz",
+ "integrity": "sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==",
+ "dev": true
+ },
+ "node_modules/@types/send": {
+ "version": "0.17.2",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.2.tgz",
+ "integrity": "sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==",
+ "dev": true,
+ "dependencies": {
+ "@types/mime": "^1",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.15.3",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.3.tgz",
+ "integrity": "sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==",
+ "dev": true,
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/mime": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/axios": {
+ "version": "1.6.5",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
+ "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
+ "dependencies": {
+ "follow-redirects": "^1.15.4",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
+ "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.1",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/colorette": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-parser": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
+ "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
+ "dependencies": {
+ "cookie": "0.4.1",
+ "cookie-signature": "1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/cookie-parser/node_modules/cookie": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
+ "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+ },
+ "node_modules/cors": {
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+ "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "16.3.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
+ "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/motdotla/dotenv?sponsor=1"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
+ },
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.18.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
+ "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.1",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.5.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.2.0",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.11.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.18.0",
+ "serve-static": "1.15.0",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.5",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
+ "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
+ "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
+ "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.12.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
+ "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
+ "node_modules/qs": {
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
+ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/send": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/serve-static": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "dependencies": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.18.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
+ "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ }
+ }
+}
diff --git a/Server/package.json b/Server/package.json
new file mode 100644
index 0000000..e9fc388
--- /dev/null
+++ b/Server/package.json
@@ -0,0 +1,48 @@
+{
+ "name": "basedserver",
+ "version": "1.0.0",
+ "description": "A base for my servers.",
+ "main": "bin/index.js",
+ "scripts": {
+ "build": "tsc",
+ "start": "npm run build && node bin/index.js",
+ "dev": "ts-node Source/index",
+ "dev:watch": "nodemon -x ts-node Source/index",
+ "check": "tsc --noEmit",
+ "lint": "prettier --check ./Source && eslint ./Source --ext .ts",
+ "format": "prettier --write ./Source && eslint ./Source --ext .ts --fix"
+ },
+ "nodemonConfig": {
+ "ext": "*.ts,*.json,*.env",
+ "ignore": [
+ "bin/**",
+ "thunder_tests/**"
+ ]
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/McMistrzYT/BasedServer.git"
+ },
+ "author": "McMistrzYT",
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/McMistrzYT/BasedServer/issues"
+ },
+ "devDependencies": {
+ "@types/cookie-parser": "^1.4.6",
+ "@types/express": "^4.17.18",
+ "@types/node": "^20.6.3",
+ "tslib": "^2.6.2",
+ "typescript": "^5.2.2"
+ },
+ "dependencies": {
+ "@types/cors": "^2.8.17",
+ "axios": "^1.6.5",
+ "colorette": "^2.0.20",
+ "cookie-parser": "^1.4.6",
+ "cors": "^2.8.5",
+ "dotenv": "^16.3.1",
+ "express": "^4.18.2"
+ },
+ "homepage": "https://github.com/McMistrzYT/BasedServer#readme"
+}
diff --git a/Server/tsconfig.json b/Server/tsconfig.json
new file mode 100644
index 0000000..7885afd
--- /dev/null
+++ b/Server/tsconfig.json
@@ -0,0 +1,107 @@
+{
+ "exclude": ["node_modules"],
+ "include": ["./Source"],
+ "compilerOptions": {
+ /* Visit https://aka.ms/tsconfig to read more about this file */
+ /* Projects */
+ "incremental": true /* Save .tsbuildinfo files to allow for incremental compilation of projects. */,
+ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
+ // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
+ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
+ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
+ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
+
+ /* Language and Environment */
+ "target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
+ "lib": [
+ "ESNext"
+ ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
+ // "jsx": "preserve", /* Specify what JSX code is generated. */
+ "experimentalDecorators": true /* Enable experimental support for TC39 stage 2 draft decorators. */,
+ "emitDecoratorMetadata": true /* Emit design-type metadata for decorated declarations in source files. */,
+ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
+ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
+ // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
+ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
+ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
+ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
+
+ /* Modules */
+ "module": "CommonJS" /* Specify what module code is generated. */,
+ // "rootDir": "./src", /* Specify the root folder within your source files. */
+ "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
+ /* Specify a set of entries that re-map imports to additional lookup locations. */
+ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
+ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
+ "types": ["node"] /* Specify type package names to be included without being referenced in a source file. */,
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
+ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ "resolveJsonModule": true /* Enable importing .json files. */,
+ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
+
+ /* JavaScript Support */
+ "allowJs": true /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */,
+ "checkJs": true /* Enable error reporting in type-checked JavaScript files. */,
+ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+
+ /* Emit */
+ "declaration": false /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
+ "declarationMap": false /* Create sourcemaps for d.ts files. */,
+ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
+ "sourceMap": true /* Create source map files for emitted JavaScript files. */,
+ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
+ "outDir": "./bin/" /* Specify an output folder for all emitted files. */,
+ // "removeComments": true, /* Disable emitting comments. */
+ // "noEmit": true, /* Disable emitting files from a compilation. */
+ "importHelpers": true /* Allow importing helper functions from tslib once per project, instead of including them per-file. */,
+ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
+ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
+ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
+ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+ // "newLine": "crlf", /* Set the newline character for emitting files. */
+ // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
+ "noEmitHelpers": true /* Disable e custom helper functions like '__extends' in compiled output. */,
+ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
+ // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
+ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
+ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+ /* Interop Constraints */
+ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
+ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
+ "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+ /* Type Checking */
+ "strict": true /* Enable all strict type-checking options. */,
+ "noImplicitAny": true /* Enable error reporting for expressions and declarations with an implied 'any' type. */,
+ "strictNullChecks": true /* When type checking, take into account 'null' and 'undefined'. */,
+ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
+ "strictPropertyInitialization": false /* Check for class properties that are declared but not set in the constructor. */,
+ // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
+ // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
+ "alwaysStrict": true /* Ensure 'use strict' is always emitted. */,
+ // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
+ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
+ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
+ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
+ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
+ // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
+ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
+ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
+ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
+ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
+
+ /* Completeness */
+ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */,
+ "noErrorTruncation": true /* Disable truncating types in error messages. */
+ },
+ "ts-node": {
+ "files": true
+ }
+}