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:
2026-05-05 00:36:17 +08:00
parent f0db19b243
commit 863358a8fd
5 changed files with 129 additions and 129 deletions
+125
View File
@@ -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
View File
@@ -1,5 +1,5 @@
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
// 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 =
typeof window === "undefined"
? // 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