Initial push
This commit is contained in:
99
server.ts
Normal file
99
server.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import next from "next"
|
||||
import { createServer } from "http"
|
||||
import { Server } from "socket.io"
|
||||
import { runMigrations } from "@/lib/db/migrate"
|
||||
import { mcProcessManager } from "@/lib/minecraft/process"
|
||||
import { setupSocketServer } from "@/lib/socket/server"
|
||||
import { auth } from "@/lib/auth/index"
|
||||
|
||||
const dev = process.env.NODE_ENV !== "production"
|
||||
const port = Number(process.env.PORT ?? 3000)
|
||||
const hostname = process.env.HOSTNAME ?? "0.0.0.0"
|
||||
|
||||
async function main(): Promise<void> {
|
||||
// ---- 1. Run DB migrations -------------------------------------------------
|
||||
console.log("[Server] Running database migrations…")
|
||||
await runMigrations()
|
||||
console.log("[Server] Migrations complete")
|
||||
|
||||
// ---- 2. Prepare Next.js app -----------------------------------------------
|
||||
const app = next({ dev, hostname, port })
|
||||
const handle = app.getRequestHandler()
|
||||
await app.prepare()
|
||||
console.log(`[Server] Next.js ready (${dev ? "development" : "production"})`)
|
||||
|
||||
// ---- 3. Create Node.js HTTP server ----------------------------------------
|
||||
const httpServer = createServer((req, res) => {
|
||||
handle(req, res).catch((err: unknown) => {
|
||||
console.error("[Server] Next.js handler error:", err)
|
||||
res.statusCode = 500
|
||||
res.end("Internal Server Error")
|
||||
})
|
||||
})
|
||||
|
||||
// ---- 4. Attach Socket.io --------------------------------------------------
|
||||
const io = new Server(httpServer, {
|
||||
cors: {
|
||||
// Restrict to same origin in production; allow all in dev for convenience
|
||||
origin: dev ? "*" : (process.env.NEXTAUTH_URL ?? `http://${hostname}:${port}`),
|
||||
credentials: true,
|
||||
},
|
||||
// Use websocket transport first, fall back to polling
|
||||
transports: ["websocket", "polling"],
|
||||
})
|
||||
|
||||
// Delegate namespace setup (auth middleware + event handlers) to the module
|
||||
setupSocketServer(io, auth)
|
||||
|
||||
// ---- 5. Start HTTP server -------------------------------------------------
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
httpServer.on("error", reject)
|
||||
httpServer.listen(port, hostname, () => {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
console.log(`[Server] Listening on http://${hostname}:${port}`)
|
||||
|
||||
// ---- 6. Initialize Minecraft process manager ------------------------------
|
||||
// (Does NOT auto-start the MC server; that is controlled through the UI)
|
||||
console.log("[Server] McProcessManager initialized")
|
||||
|
||||
// ---- 7. Graceful shutdown -------------------------------------------------
|
||||
const shutdown = async (signal: string): Promise<never> => {
|
||||
console.log(`\n[Server] Received ${signal}, shutting down…`)
|
||||
|
||||
// Stop accepting new connections
|
||||
httpServer.close()
|
||||
|
||||
// Disconnect all Socket.io clients
|
||||
await io.close()
|
||||
|
||||
// Stop the Minecraft server gracefully if it is running
|
||||
const status = mcProcessManager.getStatus()
|
||||
if (status.running) {
|
||||
console.log("[Server] Stopping Minecraft server…")
|
||||
try {
|
||||
await mcProcessManager.stop(false)
|
||||
} catch {
|
||||
// If graceful stop fails, force kill
|
||||
try {
|
||||
await mcProcessManager.stop(true)
|
||||
} catch (err) {
|
||||
console.error("[Server] Force stop failed:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log("[Server] Goodbye.")
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
process.on("SIGTERM", () => void shutdown("SIGTERM"))
|
||||
process.on("SIGINT", () => void shutdown("SIGINT"))
|
||||
}
|
||||
|
||||
main().catch((err: unknown) => {
|
||||
console.error("[Server] Fatal startup error:", err)
|
||||
process.exit(1)
|
||||
})
|
||||
Reference in New Issue
Block a user