refactor: migrate web server to centralized logger
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
import { serve, spawn, type Subprocess } from "bun";
|
||||
import { join, resolve, dirname } from "path";
|
||||
import { logger } from "@shared/lib/logger";
|
||||
|
||||
export interface WebServerConfig {
|
||||
port?: number;
|
||||
@@ -39,7 +40,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
const isDev = process.env.NODE_ENV !== "production";
|
||||
|
||||
if (isDev) {
|
||||
console.log("🛠️ Starting Web Bundler in Watch Mode...");
|
||||
logger.info("web", "Starting Web Bundler in Watch Mode...");
|
||||
try {
|
||||
buildProcess = spawn(["bun", "run", "build.ts", "--watch"], {
|
||||
cwd: webRoot,
|
||||
@@ -47,7 +48,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
stderr: "inherit",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to start build process:", error);
|
||||
logger.error("web", "Failed to start build process", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +76,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
// Security Check: limit concurrent connections
|
||||
const currentConnections = server.pendingWebSockets;
|
||||
if (currentConnections >= MAX_CONNECTIONS) {
|
||||
console.warn(`⚠️ [WS] Connection rejected: limit reached (${currentConnections}/${MAX_CONNECTIONS})`);
|
||||
logger.warn("web", `Connection rejected: limit reached (${currentConnections}/${MAX_CONNECTIONS})`);
|
||||
return new Response("Connection limit reached", { status: 429 });
|
||||
}
|
||||
|
||||
@@ -94,7 +95,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
const stats = await getFullDashboardStats();
|
||||
return Response.json(stats);
|
||||
} catch (error) {
|
||||
console.error("Error fetching dashboard stats:", error);
|
||||
logger.error("web", "Error fetching dashboard stats", error);
|
||||
return Response.json(
|
||||
{ error: "Failed to fetch dashboard statistics" },
|
||||
{ status: 500 }
|
||||
@@ -124,7 +125,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
const activity = await activityPromise;
|
||||
return Response.json(activity);
|
||||
} catch (error) {
|
||||
console.error("Error fetching activity stats:", error);
|
||||
logger.error("web", "Error fetching activity stats", error);
|
||||
return Response.json(
|
||||
{ error: "Failed to fetch activity statistics" },
|
||||
{ status: 500 }
|
||||
@@ -160,7 +161,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
return Response.json(result);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error executing administrative action:", error);
|
||||
logger.error("web", "Error executing administrative action", error);
|
||||
return Response.json(
|
||||
{ error: "Failed to execute administrative action" },
|
||||
{ status: 500 }
|
||||
@@ -196,7 +197,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
return Response.json({ success: true });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Settings error:", error);
|
||||
logger.error("web", "Settings error", error);
|
||||
return Response.json(
|
||||
{ error: "Failed to process settings request", details: error instanceof Error ? error.message : String(error) },
|
||||
{ status: 400 }
|
||||
@@ -235,7 +236,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
|
||||
return Response.json({ roles, channels, commands });
|
||||
} catch (error) {
|
||||
console.error("Error fetching settings meta:", error);
|
||||
logger.error("web", "Error fetching settings meta", error);
|
||||
return Response.json(
|
||||
{ error: "Failed to fetch metadata" },
|
||||
{ status: 500 }
|
||||
@@ -294,7 +295,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
websocket: {
|
||||
open(ws) {
|
||||
ws.subscribe("dashboard");
|
||||
console.log(`🔌 [WS] Client connected. Total: ${server.pendingWebSockets}`);
|
||||
logger.debug("web", `Client connected. Total: ${server.pendingWebSockets}`);
|
||||
|
||||
// Send initial stats
|
||||
getFullDashboardStats().then(stats => {
|
||||
@@ -308,7 +309,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
const stats = await getFullDashboardStats();
|
||||
server.publish("dashboard", JSON.stringify({ type: "STATS_UPDATE", data: stats }));
|
||||
} catch (error) {
|
||||
console.error("Error in stats broadcast:", error);
|
||||
logger.error("web", "Error in stats broadcast", error);
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
@@ -319,7 +320,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
|
||||
// Defense-in-depth: redundant length check before parsing
|
||||
if (messageStr.length > MAX_PAYLOAD_BYTES) {
|
||||
console.error("❌ [WS] Payload exceeded maximum limit");
|
||||
logger.error("web", "Payload exceeded maximum limit");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -328,7 +329,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
const parsed = WsMessageSchema.safeParse(rawData);
|
||||
|
||||
if (!parsed.success) {
|
||||
console.error("❌ [WS] Invalid message format:", parsed.error.issues);
|
||||
logger.error("web", "Invalid message format", parsed.error.issues);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -336,12 +337,12 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
ws.send(JSON.stringify({ type: "PONG" }));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("❌ [WS] Failed to handle message:", e instanceof Error ? e.message : "Malformed JSON");
|
||||
logger.error("web", "Failed to handle message", e);
|
||||
}
|
||||
},
|
||||
close(ws) {
|
||||
ws.unsubscribe("dashboard");
|
||||
console.log(`🔌 [WS] Client disconnected. Total remaining: ${server.pendingWebSockets}`);
|
||||
logger.debug("web", `Client disconnected. Total remaining: ${server.pendingWebSockets}`);
|
||||
|
||||
// Stop broadcast interval if no clients left
|
||||
if (server.pendingWebSockets === 0 && statsBroadcastInterval) {
|
||||
@@ -382,7 +383,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
// Helper to unwrap result or return default
|
||||
const unwrap = <T>(result: PromiseSettledResult<T>, defaultValue: T, name: string): T => {
|
||||
if (result.status === 'fulfilled') return result.value;
|
||||
console.error(`Failed to fetch ${name}:`, result.reason);
|
||||
logger.error("web", `Failed to fetch ${name}`, result.reason);
|
||||
return defaultValue;
|
||||
};
|
||||
|
||||
@@ -403,7 +404,7 @@ export async function createWebServer(config: WebServerConfig = {}): Promise<Web
|
||||
const recentEvents = unwrap(results[4], [], 'recentEvents');
|
||||
const totalItems = unwrap(results[5], 0, 'totalItems');
|
||||
const activeLootdrops = unwrap(results[6], [], 'activeLootdrops');
|
||||
const leaderboards = unwrap(results[7], { topLevels: [], topWealth: [] }, 'leaderboards');
|
||||
const leaderboards = unwrap(results[7], { topLevels: [], topWealth: [], topNetWorth: [] }, 'leaderboards');
|
||||
const lootdropState = unwrap(results[8], undefined, 'lootdropState');
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user