feat: add performance entry submit and autocomplete API

This commit is contained in:
2026-04-26 10:11:38 -05:00
parent 877aa766e7
commit 13ef29c6c0
3 changed files with 174 additions and 0 deletions
+2
View File
@@ -9,6 +9,7 @@ import {
hardwareRoutes, hardwareRoutes,
performanceRoutes, performanceRoutes,
performanceVerifyRoutes, performanceVerifyRoutes,
performanceSubmitRoutes,
presetsRoutes, presetsRoutes,
presetUpvoteRoutes, presetUpvoteRoutes,
presetSettingsRoutes, presetSettingsRoutes,
@@ -64,6 +65,7 @@ export const app = new Elysia({ prefix: "/api" })
// Performance // Performance
.use(performanceRoutes) .use(performanceRoutes)
.use(performanceVerifyRoutes) .use(performanceVerifyRoutes)
.use(performanceSubmitRoutes)
// Presets // Presets
.use(presetsRoutes) .use(presetsRoutes)
.use(presetUpvoteRoutes) .use(presetUpvoteRoutes)
+1
View File
@@ -3,6 +3,7 @@ export { userRoutes } from "./user"
export { gamesRoutes, gameVersionsRoutes } from "./games" export { gamesRoutes, gameVersionsRoutes } from "./games"
export { hardwareRoutes } from "./hardware" export { hardwareRoutes } from "./hardware"
export { performanceRoutes, performanceVerifyRoutes } from "./performance" export { performanceRoutes, performanceVerifyRoutes } from "./performance"
export { performanceSubmitRoutes } from "./performance-submit"
export { export {
presetsRoutes, presetsRoutes,
presetUpvoteRoutes, presetUpvoteRoutes,
+171
View File
@@ -0,0 +1,171 @@
import { Elysia, t } from "elysia"
import { auth } from "@/lib/auth"
import { db } from "@/lib/db/index"
import {
performanceEntries,
gameVersions,
hardware,
} from "@/lib/db/schema"
import { eq, sql, and } from "drizzle-orm"
import { requireRole } from "@/lib/auth/guard"
export const performanceSubmitRoutes = new Elysia({ prefix: "/performance" })
.get(
"/autocomplete",
async ({ query }) => {
const field = query.field
if (field !== "protonVersion" && field !== "osVersion") {
return { data: [] }
}
const results = await db
.select({ value: performanceEntries[field] })
.from(performanceEntries)
.where(sql`${performanceEntries[field]} IS NOT NULL`)
.groupBy(performanceEntries[field])
.orderBy(sql`count(*) DESC`)
.limit(20)
return {
data: results
.map((r) => r.value)
.filter((v): v is string => v !== null),
}
},
{
query: t.Object({
field: t.Union([
t.Literal("protonVersion"),
t.Literal("osVersion"),
]),
}),
},
)
.get(
"/hardware",
async () => {
const devices = await db
.select({
slug: hardware.slug,
name: hardware.name,
deviceType: hardware.deviceType,
})
.from(hardware)
.orderBy(hardware.sortOrder)
return { data: devices }
},
)
.post(
"/submit",
async ({ request, body, set }) => {
const guard = await requireRole(request.headers, [
"user",
"contributor",
"admin",
])
if (!guard.ok) {
set.status = guard.status
return { error: guard.error }
}
// Verify the game version exists
const [version] = await db
.select({ id: gameVersions.id })
.from(gameVersions)
.where(eq(gameVersions.id, body.versionId))
.limit(1)
if (!version) {
set.status = 404
return { error: "Game version not found" }
}
// Verify hardware exists
const [device] = await db
.select({ slug: hardware.slug })
.from(hardware)
.where(eq(hardware.slug, body.hardwareSlug))
.limit(1)
if (!device) {
set.status = 404
return { error: "Hardware not found" }
}
// Create the performance entry
const [entry] = await db
.insert(performanceEntries)
.values({
versionId: body.versionId,
hardwareSlug: body.hardwareSlug,
userId: guard.user.id,
fpsAvg: body.fpsAvg,
fpsLow: body.fpsLow ?? null,
fpsHigh: body.fpsHigh ?? null,
protonVersion: body.protonVersion ?? null,
osVersion: body.osVersion ?? null,
fsrVersion: body.fsrVersion ?? "none",
frameGenMethod: body.frameGenMethod ?? "none",
loadTimeSsd: body.loadTimeSsd ?? null,
loadTimeSd: body.loadTimeSd ?? null,
launchOptions: body.launchOptions ?? null,
settingsJson: body.settingsJson ?? null,
userNotes: body.userNotes ?? null,
})
.returning()
set.status = 201
return {
id: entry.id,
createdAt: entry.createdAt.toISOString(),
}
},
{
body: t.Object({
versionId: t.String(),
hardwareSlug: t.String(),
fpsAvg: t.Number(),
fpsLow: t.Optional(t.Union([t.Number(), t.Null()])),
fpsHigh: t.Optional(t.Union([t.Number(), t.Null()])),
protonVersion: t.Optional(t.Union([t.String(), t.Null()])),
osVersion: t.Optional(t.Union([t.String(), t.Null()])),
fsrVersion: t.Optional(
t.Union([
t.Literal("none"),
t.Literal("fsr1"),
t.Literal("fsr2"),
t.Literal("fsr3"),
]),
),
frameGenMethod: t.Optional(
t.Union([
t.Literal("none"),
t.Literal("fsr_fg"),
t.Literal("dlss_fg"),
]),
),
loadTimeSsd: t.Optional(t.Union([t.Number(), t.Null()])),
loadTimeSd: t.Optional(t.Union([t.Number(), t.Null()])),
launchOptions: t.Optional(t.Union([t.String(), t.Null()])),
settingsJson: t.Optional(
t.Union([
t.Array(
t.Object({
category: t.String(),
settings: t.Array(
t.Object({
title: t.String(),
value: t.Union([t.String(), t.Number(), t.Boolean()]),
}),
),
}),
),
t.Null(),
]),
),
userNotes: t.Optional(t.Union([t.String(), t.Null()])),
}),
},
)