fix: resolve Next.js 16 build errors
- Extract Elysia app from route.ts into lib/api/app.ts to avoid
Next.js 16 invalid export validation ('app' is not a valid route
export field)
- Remove runtime='nodejs' from opengraph-image.tsx (invalid segment
config in Next.js 16)
- Replace computed revalidate expression in sitemap.ts with literal
(Next.js cannot statically evaluate BinaryExpression for segment
configs)
- Update eden.ts imports to match new app.ts location
This commit is contained in:
@@ -1,131 +1,7 @@
|
|||||||
import { Elysia } from "elysia"
|
import { app } from "@/lib/api/app"
|
||||||
import { auth } from "@/lib/auth"
|
|
||||||
import { rateLimit } from "@/lib/auth/rate-limit"
|
|
||||||
import {
|
|
||||||
healthRoutes,
|
|
||||||
userRoutes,
|
|
||||||
gamesRoutes,
|
|
||||||
gameVersionsRoutes,
|
|
||||||
gameSyncRoutes,
|
|
||||||
hardwareRoutes,
|
|
||||||
hardwareStatsRoutes,
|
|
||||||
performanceRoutes,
|
|
||||||
performanceVerifyRoutes,
|
|
||||||
performanceSubmitRoutes,
|
|
||||||
commentsRoutes,
|
|
||||||
savedGamesRoutes,
|
|
||||||
reportRoutes,
|
|
||||||
contactRoutes,
|
|
||||||
adminReportRoutes,
|
|
||||||
adminPerformanceRoutes,
|
|
||||||
adminCommentRoutes,
|
|
||||||
} from "@/lib/api"
|
|
||||||
import { steamSearchRoutes } from "@/lib/api/steam-search"
|
|
||||||
import { searchUnifiedRoutes } from "@/lib/api/search-unified"
|
|
||||||
import { gameStubRoutes } from "@/lib/api/game-stub"
|
|
||||||
import { gameStatsRoutes } from "@/lib/api/game-stats"
|
|
||||||
import { gamesManualRoutes } from "@/lib/api/games-manual"
|
|
||||||
import { compareRoutes } from "@/lib/api/compare"
|
|
||||||
import { playabilityRoutes } from "@/lib/api/playability"
|
|
||||||
import { steamReviewRoutes } from "@/lib/api/steam-reviews"
|
|
||||||
import { communitySuggestionRoutes } from "@/lib/api/community-suggestions"
|
|
||||||
import { gamesListingRoutes } from "@/lib/api/games-listing"
|
|
||||||
import { steamgridProxyRoutes } from "@/lib/api/steamgrid-proxy"
|
|
||||||
import { dashboardRoutes } from "@/lib/api/dashboard"
|
|
||||||
import { savedFilterRoutes } from "@/lib/api/saved-filters"
|
|
||||||
|
|
||||||
const betterAuth = new Elysia({ name: "better-auth" })
|
|
||||||
.mount(auth.handler)
|
|
||||||
.macro({
|
|
||||||
auth: {
|
|
||||||
async resolve({ status, request: { headers } }) {
|
|
||||||
const session = await auth.api.getSession({
|
|
||||||
headers,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!session) return status(401)
|
|
||||||
|
|
||||||
return {
|
|
||||||
user: session.user,
|
|
||||||
session: session.session,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const app = new Elysia({ prefix: "/api" })
|
|
||||||
.onError(({ code, error, set, request }) => {
|
|
||||||
console.error(
|
|
||||||
`[API Error] ${code} ${request.url}`,
|
|
||||||
error instanceof Error ? error.message : error,
|
|
||||||
)
|
|
||||||
set.status = code === "NOT_FOUND" ? 404 : 500
|
|
||||||
return {
|
|
||||||
error: code === "NOT_FOUND" ? "Not found" : "Internal server error",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.use(rateLimit(60, 100))
|
|
||||||
.use(betterAuth)
|
|
||||||
// Health
|
|
||||||
.use(healthRoutes)
|
|
||||||
// Users
|
|
||||||
.use(userRoutes)
|
|
||||||
// Games + Versions
|
|
||||||
.use(gamesRoutes)
|
|
||||||
.use(gameVersionsRoutes)
|
|
||||||
.use(gameSyncRoutes)
|
|
||||||
.use(gamesListingRoutes)
|
|
||||||
// Hardware
|
|
||||||
.use(hardwareRoutes)
|
|
||||||
.use(hardwareStatsRoutes)
|
|
||||||
// Performance
|
|
||||||
.use(performanceRoutes)
|
|
||||||
.use(performanceVerifyRoutes)
|
|
||||||
.use(performanceSubmitRoutes)
|
|
||||||
.use(reportRoutes)
|
|
||||||
.use(adminReportRoutes)
|
|
||||||
.use(adminPerformanceRoutes)
|
|
||||||
.use(adminCommentRoutes)
|
|
||||||
// Comments
|
|
||||||
.use(commentsRoutes)
|
|
||||||
// Steam search proxy
|
|
||||||
.use(steamSearchRoutes)
|
|
||||||
// Unified search
|
|
||||||
.use(searchUnifiedRoutes)
|
|
||||||
// Game stub creation
|
|
||||||
.use(gameStubRoutes)
|
|
||||||
// SteamGridDB proxy
|
|
||||||
.use(steamgridProxyRoutes)
|
|
||||||
// Game stats aggregation
|
|
||||||
.use(gameStatsRoutes)
|
|
||||||
// Manual game creation
|
|
||||||
.use(gamesManualRoutes)
|
|
||||||
// Saved games
|
|
||||||
.use(savedGamesRoutes)
|
|
||||||
// Contact form
|
|
||||||
.use(contactRoutes)
|
|
||||||
// Compare
|
|
||||||
.use(compareRoutes)
|
|
||||||
// Playability
|
|
||||||
.use(playabilityRoutes)
|
|
||||||
// Steam reviews
|
|
||||||
.use(steamReviewRoutes)
|
|
||||||
// Community suggestions
|
|
||||||
.use(communitySuggestionRoutes)
|
|
||||||
// Saved filters
|
|
||||||
.use(savedFilterRoutes)
|
|
||||||
// Dashboard
|
|
||||||
.use(dashboardRoutes)
|
|
||||||
// Root
|
|
||||||
.get("/", () => ({
|
|
||||||
name: "DeckyVault API",
|
|
||||||
version: "2026.0.9",
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const GET = app.fetch
|
export const GET = app.fetch
|
||||||
export const POST = app.fetch
|
export const POST = app.fetch
|
||||||
export const PUT = app.fetch
|
export const PUT = app.fetch
|
||||||
export const DELETE = app.fetch
|
export const DELETE = app.fetch
|
||||||
export const PATCH = app.fetch
|
export const PATCH = app.fetch
|
||||||
|
|
||||||
export type App = typeof app
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { db } from "@/lib/db/index"
|
|||||||
import { hardware, performanceEntries, gameVersions, games } from "@/lib/db/schema"
|
import { hardware, performanceEntries, gameVersions, games } from "@/lib/db/schema"
|
||||||
import { eq, and, sql } from "drizzle-orm"
|
import { eq, and, sql } from "drizzle-orm"
|
||||||
|
|
||||||
export const runtime = "nodejs"
|
|
||||||
export const dynamic = "force-dynamic"
|
export const dynamic = "force-dynamic"
|
||||||
export const alt = "Device benchmarks on DeckyVault"
|
export const alt = "Device benchmarks on DeckyVault"
|
||||||
export const size = { width: 1200, height: 630 }
|
export const size = { width: 1200, height: 630 }
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ import { fetchDynamicEntries } from "@/lib/sitemap/fetch-dynamic-entries"
|
|||||||
* On-demand purging is handled by `/api/revalidate-sitemap` which
|
* On-demand purging is handled by `/api/revalidate-sitemap` which
|
||||||
* calls `revalidatePath("/sitemap.xml")`.
|
* calls `revalidatePath("/sitemap.xml")`.
|
||||||
*/
|
*/
|
||||||
export const revalidate = Number(process.env.SITEMAP_REVALIDATE_SECONDS) || 3600
|
export const revalidate = 3600
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the sitemap for deckyvault.xyz.
|
* Generates the sitemap for deckyvault.xyz.
|
||||||
|
|||||||
+125
@@ -0,0 +1,125 @@
|
|||||||
|
import { Elysia } from "elysia"
|
||||||
|
import { auth } from "@/lib/auth"
|
||||||
|
import { rateLimit } from "@/lib/auth/rate-limit"
|
||||||
|
import {
|
||||||
|
healthRoutes,
|
||||||
|
userRoutes,
|
||||||
|
gamesRoutes,
|
||||||
|
gameVersionsRoutes,
|
||||||
|
gameSyncRoutes,
|
||||||
|
hardwareRoutes,
|
||||||
|
hardwareStatsRoutes,
|
||||||
|
performanceRoutes,
|
||||||
|
performanceVerifyRoutes,
|
||||||
|
performanceSubmitRoutes,
|
||||||
|
commentsRoutes,
|
||||||
|
savedGamesRoutes,
|
||||||
|
reportRoutes,
|
||||||
|
contactRoutes,
|
||||||
|
adminReportRoutes,
|
||||||
|
adminPerformanceRoutes,
|
||||||
|
adminCommentRoutes,
|
||||||
|
} from "@/lib/api"
|
||||||
|
import { steamSearchRoutes } from "@/lib/api/steam-search"
|
||||||
|
import { searchUnifiedRoutes } from "@/lib/api/search-unified"
|
||||||
|
import { gameStubRoutes } from "@/lib/api/game-stub"
|
||||||
|
import { gameStatsRoutes } from "@/lib/api/game-stats"
|
||||||
|
import { gamesManualRoutes } from "@/lib/api/games-manual"
|
||||||
|
import { compareRoutes } from "@/lib/api/compare"
|
||||||
|
import { playabilityRoutes } from "@/lib/api/playability"
|
||||||
|
import { steamReviewRoutes } from "@/lib/api/steam-reviews"
|
||||||
|
import { communitySuggestionRoutes } from "@/lib/api/community-suggestions"
|
||||||
|
import { gamesListingRoutes } from "@/lib/api/games-listing"
|
||||||
|
import { steamgridProxyRoutes } from "@/lib/api/steamgrid-proxy"
|
||||||
|
import { dashboardRoutes } from "@/lib/api/dashboard"
|
||||||
|
import { savedFilterRoutes } from "@/lib/api/saved-filters"
|
||||||
|
|
||||||
|
const betterAuth = new Elysia({ name: "better-auth" })
|
||||||
|
.mount(auth.handler)
|
||||||
|
.macro({
|
||||||
|
auth: {
|
||||||
|
async resolve({ status, request: { headers } }) {
|
||||||
|
const session = await auth.api.getSession({
|
||||||
|
headers,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!session) return status(401)
|
||||||
|
|
||||||
|
return {
|
||||||
|
user: session.user,
|
||||||
|
session: session.session,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const app = new Elysia({ prefix: "/api" })
|
||||||
|
.onError(({ code, error, set, request }) => {
|
||||||
|
console.error(
|
||||||
|
`[API Error] ${code} ${request.url}`,
|
||||||
|
error instanceof Error ? error.message : error,
|
||||||
|
)
|
||||||
|
set.status = code === "NOT_FOUND" ? 404 : 500
|
||||||
|
return {
|
||||||
|
error: code === "NOT_FOUND" ? "Not found" : "Internal server error",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.use(rateLimit(60, 100))
|
||||||
|
.use(betterAuth)
|
||||||
|
// Health
|
||||||
|
.use(healthRoutes)
|
||||||
|
// Users
|
||||||
|
.use(userRoutes)
|
||||||
|
// Games + Versions
|
||||||
|
.use(gamesRoutes)
|
||||||
|
.use(gameVersionsRoutes)
|
||||||
|
.use(gameSyncRoutes)
|
||||||
|
.use(gamesListingRoutes)
|
||||||
|
// Hardware
|
||||||
|
.use(hardwareRoutes)
|
||||||
|
.use(hardwareStatsRoutes)
|
||||||
|
// Performance
|
||||||
|
.use(performanceRoutes)
|
||||||
|
.use(performanceVerifyRoutes)
|
||||||
|
.use(performanceSubmitRoutes)
|
||||||
|
.use(reportRoutes)
|
||||||
|
.use(adminReportRoutes)
|
||||||
|
.use(adminPerformanceRoutes)
|
||||||
|
.use(adminCommentRoutes)
|
||||||
|
// Comments
|
||||||
|
.use(commentsRoutes)
|
||||||
|
// Steam search proxy
|
||||||
|
.use(steamSearchRoutes)
|
||||||
|
// Unified search
|
||||||
|
.use(searchUnifiedRoutes)
|
||||||
|
// Game stub creation
|
||||||
|
.use(gameStubRoutes)
|
||||||
|
// SteamGridDB proxy
|
||||||
|
.use(steamgridProxyRoutes)
|
||||||
|
// Game stats aggregation
|
||||||
|
.use(gameStatsRoutes)
|
||||||
|
// Manual game creation
|
||||||
|
.use(gamesManualRoutes)
|
||||||
|
// Saved games
|
||||||
|
.use(savedGamesRoutes)
|
||||||
|
// Contact form
|
||||||
|
.use(contactRoutes)
|
||||||
|
// Compare
|
||||||
|
.use(compareRoutes)
|
||||||
|
// Playability
|
||||||
|
.use(playabilityRoutes)
|
||||||
|
// Steam reviews
|
||||||
|
.use(steamReviewRoutes)
|
||||||
|
// Community suggestions
|
||||||
|
.use(communitySuggestionRoutes)
|
||||||
|
// Saved filters
|
||||||
|
.use(savedFilterRoutes)
|
||||||
|
// Dashboard
|
||||||
|
.use(dashboardRoutes)
|
||||||
|
// Root
|
||||||
|
.get("/", () => ({
|
||||||
|
name: "DeckyVault API",
|
||||||
|
version: "2026.0.9",
|
||||||
|
}))
|
||||||
|
|
||||||
|
export type App = typeof app
|
||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
import { treaty } from "@elysia/eden"
|
import { treaty } from "@elysia/eden"
|
||||||
import type { App } from "@/app/api/[[...slugs]]/route"
|
import type { App } from "@/lib/api/app"
|
||||||
|
|
||||||
// Use require() on the server branch to prevent the client bundler from
|
// Use require() on the server branch to prevent the client bundler from
|
||||||
// pulling in Elysia and the route module. The typeof window check is the
|
// pulling in Elysia and the route module. The typeof window check is the
|
||||||
@@ -7,5 +7,5 @@ import type { App } from "@/app/api/[[...slugs]]/route"
|
|||||||
export const api =
|
export const api =
|
||||||
typeof window === "undefined"
|
typeof window === "undefined"
|
||||||
? // eslint-disable-next-line @typescript-eslint/no-require-imports
|
? // eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
treaty((require("../app/api/[[...slugs]]/route") as { app: App }).app).api
|
treaty((require("@/lib/api/app") as { app: App }).app).api
|
||||||
: treaty<App>(process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3000").api
|
: treaty<App>(process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3000").api
|
||||||
|
|||||||
Reference in New Issue
Block a user