From 3fe9788a4fad317db3a756f2d331a26f592b8b4f Mon Sep 17 00:00:00 2001 From: Lncvrt Date: Sat, 8 Nov 2025 19:13:23 -0700 Subject: [PATCH] Switch to using a different method of database access --- bun.lock | 4 +- package.json | 2 +- src/index.ts | 58 +++---- src/lib/tables.ts | 62 ++++--- src/lib/util.ts | 28 ++- src/routes/launcher/latest.ts | 27 +-- src/routes/launcher/loader/latest.ts | 6 +- src/routes/launcher/loader/update-data.ts | 154 ++++++++-------- src/routes/launcher/versions.ts | 203 ++++++++++++---------- 9 files changed, 304 insertions(+), 240 deletions(-) diff --git a/bun.lock b/bun.lock index 7c626ef..e68eab0 100644 --- a/bun.lock +++ b/bun.lock @@ -11,7 +11,7 @@ "mysql2": "3.15.3", }, "devDependencies": { - "bun-types": "1.3.1", + "bun-types": "1.3.2", }, }, }, @@ -32,7 +32,7 @@ "aws-ssl-profiles": ["aws-ssl-profiles@1.1.2", "", {}, "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g=="], - "bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="], + "bun-types": ["bun-types@1.3.2", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-i/Gln4tbzKNuxP70OWhJRZz1MRfvqExowP7U6JKoI8cntFrtxg7RJK3jvz7wQW54UuvNC8tbKHHri5fy74FVqg=="], "cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="], diff --git a/package.json b/package.json index b08724b..cb6faa8 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "mysql2": "3.15.3" }, "devDependencies": { - "bun-types": "1.3.1" + "bun-types": "1.3.2" }, "module": "src/index.js" } diff --git a/src/index.ts b/src/index.ts index 9caca33..ba5f661 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,37 +1,35 @@ -import { Elysia } from "elysia"; -import { cors } from "@elysiajs/cors" -import { jsonResponse } from "./lib/util"; -import { drizzle } from 'drizzle-orm/mysql2'; -import mysql from 'mysql2/promise'; +import { Elysia } from 'elysia' +import { cors } from '@elysiajs/cors' +import { jsonResponse } from './lib/util' import dotenv from 'dotenv' -import { handler as launcherVersionsHandler } from "./routes/launcher/versions"; -import { handler as launcherLatestHandler } from "./routes/launcher/latest"; -import { handler as launcherLoaderLatestHandler } from "./routes/launcher/loader/latest"; -import { handler as launcherLoaderUpdateDataHandler } from "./routes/launcher/loader/update-data"; +import { handler as launcherVersionsHandler } from './routes/launcher/versions' +import { handler as launcherLatestHandler } from './routes/launcher/latest' +import { handler as launcherLoaderLatestHandler } from './routes/launcher/loader/latest' +import { handler as launcherLoaderUpdateDataHandler } from './routes/launcher/loader/update-data' dotenv.config() -const connection = await mysql.createConnection({ - host: process.env.DB_HOST ?? 'localhost', - port: Number(process.env.DB_PORT) || 3306, - user: process.env.DB_USER ?? '', - password: process.env.DB_PASS ?? '', - database: process.env.DB_NAME ?? '' -}); +const app = new Elysia().use( + cors({ + origin: '*', + methods: ['POST', 'GET'] + }) +) -const db = drizzle(connection); +app.get('/launcher/versions', context => launcherVersionsHandler(context)) +app.get('/launcher/latest', launcherLatestHandler) +app.get('/launcher/loader/latest', launcherLoaderLatestHandler) +app.get('/launcher/loader/update-data', context => + launcherLoaderUpdateDataHandler(context) +) +app.all('*', () => + jsonResponse( + { + message: 'No endpoint found (are you using the correct request method?)' + }, + 404 + ) +) -const app = new Elysia() - .use(cors({ - origin: "*", - methods: ["POST", "GET"] - })) - -app.get("/launcher/versions", (context) => launcherVersionsHandler(context, db)) -app.get("/launcher/latest", () => launcherLatestHandler(db)) -app.get("/launcher/loader/latest", launcherLoaderLatestHandler) -app.get("/launcher/loader/update-data", (context) => launcherLoaderUpdateDataHandler(context, db)) -app.all("*", () => jsonResponse({ message: "No endpoint found (are you using the correct request method?)" }, 404)) - -app.listen(3342) \ No newline at end of file +app.listen(3342) diff --git a/src/lib/tables.ts b/src/lib/tables.ts index 3129e20..6835395 100644 --- a/src/lib/tables.ts +++ b/src/lib/tables.ts @@ -1,35 +1,45 @@ -import { bigint, boolean, int, mysqlTable, text, varchar } from "drizzle-orm/mysql-core"; +import { + bigint, + boolean, + int, + mysqlTable, + text, + varchar +} from 'drizzle-orm/mysql-core' export const launcherGames = mysqlTable('launchergames', { - id: int('id').primaryKey().autoincrement(), - name: text('name').notNull(), - official: boolean('official').notNull().default(false), - verified: boolean('verified').notNull().default(false), - developer: varchar('developer', { length: 32 }), - cutOff: int('cutOff').notNull().default(-1) + id: int('id').primaryKey().autoincrement(), + name: text('name').notNull(), + official: boolean('official').notNull().default(false), + verified: boolean('verified').notNull().default(false), + developer: varchar('developer', { length: 32 }), + cutOff: int('cutOff').notNull().default(-1) }) export const launcherVersions = mysqlTable('launcherversions', { - id: varchar('id', { length: 24 }).primaryKey(), - versionName: text('versionName').notNull(), - releaseDate: bigint('releaseDate', { mode: 'number' }).notNull(), - downloadUrls: text('downloadUrls').notNull(), - platforms: text('platforms').notNull(), - executables: text('executables').notNull(), - hidden: boolean('hidden').notNull().default(false), - game: int('game').notNull().default(0).references(() => launcherGames.id), - place: int('place').notNull().default(0), - sha512sums: text('sha512sums').notNull().default("[]"), - sizes: text('sizes').notNull().default("[]") + id: varchar('id', { length: 24 }).primaryKey(), + versionName: text('versionName').notNull(), + releaseDate: bigint('releaseDate', { mode: 'number' }).notNull(), + downloadUrls: text('downloadUrls').notNull(), + platforms: text('platforms').notNull(), + executables: text('executables').notNull(), + hidden: boolean('hidden').notNull().default(false), + game: int('game') + .notNull() + .default(0) + .references(() => launcherGames.id), + place: int('place').notNull().default(0), + sha512sums: text('sha512sums').notNull().default('[]'), + sizes: text('sizes').notNull().default('[]') }) export const launcherUpdates = mysqlTable('launcherupdates', { - id: varchar('id', { length: 24 }).primaryKey(), - releaseDate: bigint('releaseDate', { mode: 'number' }).notNull(), - downloadUrls: text('downloadUrls').notNull(), - platforms: text('platforms').notNull(), - executables: text('executables').notNull(), - hidden: boolean('hidden').notNull().default(false), - place: int('place').notNull().default(0), - sha512sums: text('sha512sums').notNull().default("[]") + id: varchar('id', { length: 24 }).primaryKey(), + releaseDate: bigint('releaseDate', { mode: 'number' }).notNull(), + downloadUrls: text('downloadUrls').notNull(), + platforms: text('platforms').notNull(), + executables: text('executables').notNull(), + hidden: boolean('hidden').notNull().default(false), + place: int('place').notNull().default(0), + sha512sums: text('sha512sums').notNull().default('[]') }) diff --git a/src/lib/util.ts b/src/lib/util.ts index dd561ce..55e0d74 100644 --- a/src/lib/util.ts +++ b/src/lib/util.ts @@ -1,6 +1,22 @@ -export function jsonResponse(data: any, status = 200) { - return new Response(JSON.stringify(data, null, 2), { - status, - headers: { "Content-Type": "application/json" } - }) -} \ No newline at end of file +import mysql from 'mysql2' +import { drizzle } from 'drizzle-orm/mysql2' +import { Connection } from 'mysql2/typings/mysql/lib/Connection' + +export function jsonResponse (data: any, status = 200) { + return new Response(JSON.stringify(data, null, 2), { + status, + headers: { 'Content-Type': 'application/json' } + }) +} + +export function getDatabaseConnection () { + const connection = mysql.createConnection({ + host: process.env.DB_HOST ?? 'localhost', + port: Number(process.env.DB_PORT) || 3306, + user: process.env.DB_USER ?? '', + password: process.env.DB_PASS ?? '', + database: process.env.DB_NAME ?? '' + }) + + return drizzle(connection) +} diff --git a/src/routes/launcher/latest.ts b/src/routes/launcher/latest.ts index e1b2283..840de6c 100644 --- a/src/routes/launcher/latest.ts +++ b/src/routes/launcher/latest.ts @@ -1,15 +1,18 @@ -import { MySql2Database } from "drizzle-orm/mysql2" -import { launcherUpdates } from "../../lib/tables" -import { desc, eq } from "drizzle-orm" +import { launcherUpdates } from '../../lib/tables' +import { desc, eq } from 'drizzle-orm' +import { getDatabaseConnection } from '../../lib/util' -export async function handler(db: MySql2Database) { - const version = await db.select({ - id: launcherUpdates.id +export async function handler () { + const db = getDatabaseConnection() + + const version = await db + .select({ + id: launcherUpdates.id }) - .from(launcherUpdates) - .where(eq(launcherUpdates.hidden, false)) - .orderBy(desc(launcherUpdates.place)) - .limit(1) + .from(launcherUpdates) + .where(eq(launcherUpdates.hidden, false)) + .orderBy(desc(launcherUpdates.place)) + .limit(1) - return version[0].id -} \ No newline at end of file + return version[0].id +} diff --git a/src/routes/launcher/loader/latest.ts b/src/routes/launcher/loader/latest.ts index bb7aff6..24cdbcd 100644 --- a/src/routes/launcher/loader/latest.ts +++ b/src/routes/launcher/loader/latest.ts @@ -1,3 +1,3 @@ -export async function handler() { - return "1.0.1" -} \ No newline at end of file +export async function handler () { + return '1.0.1' +} diff --git a/src/routes/launcher/loader/update-data.ts b/src/routes/launcher/loader/update-data.ts index 3186805..57fd672 100644 --- a/src/routes/launcher/loader/update-data.ts +++ b/src/routes/launcher/loader/update-data.ts @@ -1,80 +1,92 @@ -import { MySql2Database } from "drizzle-orm/mysql2"; -import { launcherUpdates } from "../../../lib/tables"; -import { desc, eq } from "drizzle-orm"; -import { jsonResponse } from "../../../lib/util"; -import { Context } from "elysia"; +import { launcherUpdates } from '../../../lib/tables' +import { desc, eq } from 'drizzle-orm' +import { getDatabaseConnection, jsonResponse } from '../../../lib/util' +import { Context } from 'elysia' -export async function handler(context: Context, db: MySql2Database) { - const platform = context.query.platform as string | undefined - const arch = context.query.arch as string | undefined - let showAll = false +export async function handler (context: Context) { + const db = getDatabaseConnection() - if (!platform || !arch) { - showAll = true + const platform = context.query.platform as string | undefined + const arch = context.query.arch as string | undefined + let showAll = false + + if (!platform || !arch) { + showAll = true + } + + let platString = null + if (!showAll) { + if (platform == 'windows') { + if (arch == 'x86_64') platString = 'windows' + else if (arch == 'aarch64') platString = 'windows-arm64' + else { + return jsonResponse( + { error: 'Unsupported architecture for Windows' }, + 400 + ) + } + } else if (platform == 'linux') { + if (arch == 'x86_64') platString = 'linux' + else { + return jsonResponse( + { error: 'Unsupported architecture for Linux' }, + 400 + ) + } + } else if (platform == 'macos') { + if (arch == 'x86_64') platString = 'macos-intel' + else if (arch == 'aarch64') platString = 'macos-silicon' + else { + return jsonResponse( + { error: 'Unsupported architecture for macOS' }, + 400 + ) + } + } else { + return jsonResponse({ error: 'Unsupported platform' }, 400) } + } - let platString = null - if (!showAll) { - if (platform == "windows") { - if (arch == "x86_64") platString = "windows" - else if (arch == "aarch64") platString = "windows-arm64" - else { - return jsonResponse({ error: "Unsupported architecture for Windows" }, 400) - } - } else if (platform == "linux") { - if (arch == "x86_64") platString = "linux" - else { - return jsonResponse({ error: "Unsupported architecture for Linux" }, 400) - } - } else if (platform == "macos") { - if (arch == "x86_64") platString = "macos-intel" - else if (arch == "aarch64") platString = "macos-silicon" - else { - return jsonResponse({ error: "Unsupported architecture for macOS" }, 400) - } - } else { - return jsonResponse({ error: "Unsupported platform" }, 400) - } - } - - const versionsRaw = await db.select({ - id: launcherUpdates.id, - releaseDate: launcherUpdates.releaseDate, - downloadUrls: launcherUpdates.downloadUrls, - platforms: launcherUpdates.platforms, - sha512sums: launcherUpdates.sha512sums + const versionsRaw = await db + .select({ + id: launcherUpdates.id, + releaseDate: launcherUpdates.releaseDate, + downloadUrls: launcherUpdates.downloadUrls, + platforms: launcherUpdates.platforms, + sha512sums: launcherUpdates.sha512sums }) - .from(launcherUpdates) - .where(eq(launcherUpdates.hidden, false)) - .orderBy(desc(launcherUpdates.place)) - .limit(1) - .execute() + .from(launcherUpdates) + .where(eq(launcherUpdates.hidden, false)) + .orderBy(desc(launcherUpdates.place)) + .limit(1) + .execute() - const versions = versionsRaw.map(v => ({ - ...v, - downloadUrls: JSON.parse(v.downloadUrls), - platforms: JSON.parse(v.platforms), - sha512sums: JSON.parse(v.sha512sums), - downloadUrl: undefined as string | undefined, - sha512sum: undefined as string | undefined + const versions = versionsRaw + .map(v => ({ + ...v, + downloadUrls: JSON.parse(v.downloadUrls), + platforms: JSON.parse(v.platforms), + sha512sums: JSON.parse(v.sha512sums), + downloadUrl: undefined as string | undefined, + sha512sum: undefined as string | undefined })) - .filter(v => { - if (showAll || !platString) { - delete v.downloadUrl - delete v.sha512sum - return true - } - const i = v.platforms.indexOf(platString) - if (i !== -1) { - v.downloadUrl = v.downloadUrls[i] - v.sha512sum = v.sha512sums[i] - delete v.downloadUrls - delete v.platforms - delete v.sha512sums - return true - } - return false - }) + .filter(v => { + if (showAll || !platString) { + delete v.downloadUrl + delete v.sha512sum + return true + } + const i = v.platforms.indexOf(platString) + if (i !== -1) { + v.downloadUrl = v.downloadUrls[i] + v.sha512sum = v.sha512sums[i] + delete v.downloadUrls + delete v.platforms + delete v.sha512sums + return true + } + return false + }) - return jsonResponse(versions[0]) + return jsonResponse(versions[0]) } diff --git a/src/routes/launcher/versions.ts b/src/routes/launcher/versions.ts index a080a2b..5d86167 100644 --- a/src/routes/launcher/versions.ts +++ b/src/routes/launcher/versions.ts @@ -1,98 +1,123 @@ -import { MySql2Database } from "drizzle-orm/mysql2"; -import { launcherGames, launcherVersions } from "../../lib/tables"; -import { asc, desc, eq } from "drizzle-orm"; -import { jsonResponse } from "../../lib/util"; -import { Context } from "elysia"; +import { launcherGames, launcherVersions } from '../../lib/tables' +import { asc, desc, eq } from 'drizzle-orm' +import { getDatabaseConnection, jsonResponse } from '../../lib/util' +import { Context } from 'elysia' -export async function handler(context: Context, db: MySql2Database) { - const platform = context.query.platform as string | undefined - const arch = context.query.arch as string | undefined - let showAll = false +export async function handler (context: Context) { + const db = getDatabaseConnection() - if (!platform || !arch) { - showAll = true - } + const platform = context.query.platform as string | undefined + const arch = context.query.arch as string | undefined + let showAll = false - let platString = null - if (!showAll) { - if (platform == "windows") { - if (arch == "x86_64") platString = "windows" - else if (arch == "aarch64") platString = "windows-arm64" - else { - return jsonResponse({ message: "Unsupported architecture for Windows", versions: null, games: null }, 400) - } - } else if (platform == "linux") { - if (arch == "x86_64") platString = "linux" - else { - return jsonResponse({ message: "Unsupported architecture for Linux", versions: null, games: null }, 400) - } - } else if (platform == "macos") { - if (arch == "x86_64" || arch == "aarch64") platString = "macos" - else { - return jsonResponse({ message: "Unsupported architecture for macOS", versions: null, games: null }, 400) - } - } else if (platform == "android") platString = "android" - else if (platform == "ios") platString = "ios" - else { - return jsonResponse({ message: "Unsupported platform", versions: null, games: null }, 400) - } - } + if (!platform || !arch) { + showAll = true + } - const versionsRaw = await db.select({ - id: launcherVersions.id, - versionName: launcherVersions.versionName, - releaseDate: launcherVersions.releaseDate, - game: launcherVersions.game, - downloadUrls: launcherVersions.downloadUrls, - platforms: launcherVersions.platforms, - executables: launcherVersions.executables, - sha512sums: launcherVersions.sha512sums, - sizes: launcherVersions.sizes - }).from(launcherVersions) - .where(eq(launcherVersions.hidden, false)) - .orderBy( - asc(launcherVersions.game), - desc(launcherVersions.place) + let platString = null + if (!showAll) { + if (platform == 'windows') { + if (arch == 'x86_64') platString = 'windows' + else if (arch == 'aarch64') platString = 'windows-arm64' + else { + return jsonResponse( + { + message: 'Unsupported architecture for Windows', + versions: null, + games: null + }, + 400 ) - .execute() + } + } else if (platform == 'linux') { + if (arch == 'x86_64') platString = 'linux' + else { + return jsonResponse( + { + message: 'Unsupported architecture for Linux', + versions: null, + games: null + }, + 400 + ) + } + } else if (platform == 'macos') { + if (arch == 'x86_64' || arch == 'aarch64') platString = 'macos' + else { + return jsonResponse( + { + message: 'Unsupported architecture for macOS', + versions: null, + games: null + }, + 400 + ) + } + } else if (platform == 'android') platString = 'android' + else if (platform == 'ios') platString = 'ios' + else { + return jsonResponse( + { message: 'Unsupported platform', versions: null, games: null }, + 400 + ) + } + } - const versions = versionsRaw.map(v => ({ - ...v, - downloadUrls: JSON.parse(v.downloadUrls), - platforms: JSON.parse(v.platforms), - executables: JSON.parse(v.executables), - sha512sums: JSON.parse(v.sha512sums), - sizes: JSON.parse(v.sizes), - downloadUrl: undefined as string | undefined, - executable: undefined as string | undefined, - sha512sum: undefined as string | undefined, - size: undefined as number | undefined + const versionsRaw = await db + .select({ + id: launcherVersions.id, + versionName: launcherVersions.versionName, + releaseDate: launcherVersions.releaseDate, + game: launcherVersions.game, + downloadUrls: launcherVersions.downloadUrls, + platforms: launcherVersions.platforms, + executables: launcherVersions.executables, + sha512sums: launcherVersions.sha512sums, + sizes: launcherVersions.sizes + }) + .from(launcherVersions) + .where(eq(launcherVersions.hidden, false)) + .orderBy(asc(launcherVersions.game), desc(launcherVersions.place)) + .execute() + + const versions = versionsRaw + .map(v => ({ + ...v, + downloadUrls: JSON.parse(v.downloadUrls), + platforms: JSON.parse(v.platforms), + executables: JSON.parse(v.executables), + sha512sums: JSON.parse(v.sha512sums), + sizes: JSON.parse(v.sizes), + downloadUrl: undefined as string | undefined, + executable: undefined as string | undefined, + sha512sum: undefined as string | undefined, + size: undefined as number | undefined })) - .filter(v => { - if (showAll || !platString) { - delete v.downloadUrl - delete v.executable - delete v.sha512sum - delete v.size - return true - } - const i = v.platforms.indexOf(platString) - if (i !== -1) { - v.downloadUrl = v.downloadUrls[i] - v.executable = v.executables[i] - v.sha512sum = v.sha512sums[i] - v.size = v.sizes[i] - delete v.downloadUrls - delete v.platforms - delete v.executables - delete v.sha512sums - delete v.sizes - return true - } - return false - }) + .filter(v => { + if (showAll || !platString) { + delete v.downloadUrl + delete v.executable + delete v.sha512sum + delete v.size + return true + } + const i = v.platforms.indexOf(platString) + if (i !== -1) { + v.downloadUrl = v.downloadUrls[i] + v.executable = v.executables[i] + v.sha512sum = v.sha512sums[i] + v.size = v.sizes[i] + delete v.downloadUrls + delete v.platforms + delete v.executables + delete v.sha512sums + delete v.sizes + return true + } + return false + }) - const games = await db.select().from(launcherGames).execute() + const games = await db.select().from(launcherGames).execute() - return jsonResponse({ versions, games }) -} \ No newline at end of file + return jsonResponse({ versions, games }) +}