refactor: centralize error handling utilities across route modules

- Introduced a new common utility module for error handling, providing consistent methods for retrieving error messages and logging errors.
- Updated individual route modules to utilize the shared error handling functions, reducing code duplication and improving maintainability.
- Ensured all routes now log errors in a standardized format, enhancing debugging and monitoring capabilities.
This commit is contained in:
Cody Seibert
2025-12-14 17:59:16 -05:00
parent 6b30271441
commit 01bae7d43e
25 changed files with 154 additions and 212 deletions

View File

@@ -3,19 +3,13 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("Agent"); const logger = createLogger("Agent");
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -22,12 +22,10 @@ export function createSendHandler(agentService: AgentService) {
}; };
if (!sessionId || !message) { if (!sessionId || !message) {
res res.status(400).json({
.status(400) success: false,
.json({ error: "sessionId and message are required",
success: false, });
error: "sessionId and message are required",
});
return; return;
} }
@@ -41,7 +39,7 @@ export function createSendHandler(agentService: AgentService) {
model, model,
}) })
.catch((error) => { .catch((error) => {
logger.error("[Agent Route] Error sending message:", error); logError(error, "Send message failed (background)");
}); });
// Return immediately - responses come via WebSocket // Return immediately - responses come via WebSocket

View File

@@ -3,6 +3,7 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import { getErrorMessage as getErrorMessageShared } from "../common.js";
const logger = createLogger("SpecRegeneration"); const logger = createLogger("SpecRegeneration");
@@ -65,9 +66,7 @@ export function logError(error: unknown, context: string): void {
); );
} }
/** import { getErrorMessage as getErrorMessageShared } from "../common.js";
* Get error message from error object
*/ // Re-export shared utility
export function getErrorMessage(error: unknown): string { export { getErrorMessageShared as getErrorMessage };
return error instanceof Error ? error.message : "Unknown error";
}

View File

@@ -87,8 +87,7 @@ export function createCreateHandler(events: EventEmitter) {
); );
res.json({ success: true }); res.json({ success: true });
} catch (error) { } catch (error) {
logger.error("❌ Route handler exception:"); logError(error, "Create spec route handler failed");
logger.error("Error:", error);
res.status(500).json({ success: false, error: getErrorMessage(error) }); res.status(500).json({ success: false, error: getErrorMessage(error) });
} }
}; };

View File

@@ -62,8 +62,7 @@ export function createGenerateFeaturesHandler(events: EventEmitter) {
); );
res.json({ success: true }); res.json({ success: true });
} catch (error) { } catch (error) {
logger.error("❌ Route handler exception:"); logError(error, "Generate features route handler failed");
logger.error("Error:", error);
res.status(500).json({ success: false, error: getErrorMessage(error) }); res.status(500).json({ success: false, error: getErrorMessage(error) });
} }
}; };

View File

@@ -90,8 +90,7 @@ export function createGenerateHandler(events: EventEmitter) {
); );
res.json({ success: true }); res.json({ success: true });
} catch (error) { } catch (error) {
logger.error("❌ Route handler exception:"); logError(error, "Generate spec route handler failed");
logger.error("Error:", error);
res.status(500).json({ success: false, error: getErrorMessage(error) }); res.status(500).json({ success: false, error: getErrorMessage(error) });
} }
}; };

View File

@@ -3,19 +3,13 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("AutoMode"); const logger = createLogger("AutoMode");
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -0,0 +1,24 @@
/**
* Common utilities shared across all route modules
*/
import { createLogger } from "../lib/logger.js";
type Logger = ReturnType<typeof createLogger>;
/**
* Get error message from error object
*/
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Create a logError function for a specific logger
* This ensures consistent error logging format across all routes
*/
export function createLogError(logger: Logger) {
return (error: unknown, context: string): void => {
logger.error(`${context}:`, error);
};
}

View File

@@ -3,19 +3,13 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("Features"); const logger = createLogger("Features");
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -3,19 +3,13 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("FS"); const logger = createLogger("FS");
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -31,10 +31,11 @@ export function createResolveDirectoryHandler() {
const stats = await fs.stat(resolvedPath); const stats = await fs.stat(resolvedPath);
if (stats.isDirectory()) { if (stats.isDirectory()) {
addAllowedPath(resolvedPath); addAllowedPath(resolvedPath);
return res.json({ res.json({
success: true, success: true,
path: resolvedPath, path: resolvedPath,
}); });
return;
} }
} catch { } catch {
// Not a valid absolute path, continue to search // Not a valid absolute path, continue to search
@@ -102,10 +103,11 @@ export function createResolveDirectoryHandler() {
// Found matching directory // Found matching directory
addAllowedPath(candidatePath); addAllowedPath(candidatePath);
return res.json({ res.json({
success: true, success: true,
path: candidatePath, path: candidatePath,
}); });
return;
} }
} catch { } catch {
// Directory doesn't exist at this location, continue searching // Directory doesn't exist at this location, continue searching

View File

@@ -3,19 +3,13 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("Git"); const logger = createLogger("Git");
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -3,12 +3,13 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("Health"); const logger = createLogger("Health");
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}

View File

@@ -3,19 +3,13 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("Models"); const logger = createLogger("Models");
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -3,19 +3,13 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("RunningAgents"); const logger = createLogger("RunningAgents");
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -3,19 +3,13 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("Sessions"); const logger = createLogger("Sessions");
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -5,6 +5,10 @@
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import path from "path"; import path from "path";
import fs from "fs/promises"; import fs from "fs/promises";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("Setup"); const logger = createLogger("Setup");
@@ -53,16 +57,6 @@ export async function persistApiKeyToEnv(
} }
} }
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -3,6 +3,10 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("Suggestions"); const logger = createLogger("Suggestions");
@@ -21,16 +25,6 @@ export function setRunningState(
currentAbortController = controller; currentAbortController = controller;
} }
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -43,7 +43,7 @@ export function createGenerateHandler(events: EventEmitter) {
// Start generation in background // Start generation in background
generateSuggestions(projectPath, suggestionType, events, abortController) generateSuggestions(projectPath, suggestionType, events, abortController)
.catch((error) => { .catch((error) => {
logger.error("[Suggestions] Error:", error); logError(error, "Generate suggestions failed (background)");
events.emit("suggestions:event", { events.emit("suggestions:event", {
type: "suggestions_error", type: "suggestions_error",
error: getErrorMessage(error), error: getErrorMessage(error),

View File

@@ -3,19 +3,13 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("Templates"); export const logger = createLogger("Templates");
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -7,10 +7,7 @@ import { spawn } from "child_process";
import path from "path"; import path from "path";
import fs from "fs/promises"; import fs from "fs/promises";
import { addAllowedPath } from "../../../lib/security.js"; import { addAllowedPath } from "../../../lib/security.js";
import { createLogger } from "../../../lib/logger.js"; import { logger, getErrorMessage, logError } from "../common.js";
import { getErrorMessage, logError } from "../common.js";
const logger = createLogger("Templates");
export function createCloneHandler() { export function createCloneHandler() {
return async (req: Request, res: Response): Promise<void> => { return async (req: Request, res: Response): Promise<void> => {
@@ -59,10 +56,11 @@ export function createCloneHandler() {
const resolvedProject = path.resolve(projectPath); const resolvedProject = path.resolve(projectPath);
const relativePath = path.relative(resolvedParent, resolvedProject); const relativePath = path.relative(resolvedParent, resolvedProject);
if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) { if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) {
return res.status(400).json({ res.status(400).json({
success: false, success: false,
error: "Invalid project name; potential path traversal attempt.", error: "Invalid project name; potential path traversal attempt.",
}); });
return;
} }
// Check if directory already exists // Check if directory already exists
@@ -199,7 +197,6 @@ export function createCloneHandler() {
projectName: sanitizedName, projectName: sanitizedName,
}); });
} catch (error) { } catch (error) {
logger.error("[Templates] Clone error:", error);
logError(error, "Clone template failed"); logError(error, "Clone template failed");
res.status(500).json({ success: false, error: getErrorMessage(error) }); res.status(500).json({ success: false, error: getErrorMessage(error) });
} }

View File

@@ -129,9 +129,11 @@ export function getTokenExpiryMs(): number {
return TOKEN_EXPIRY_MS; return TOKEN_EXPIRY_MS;
} }
/** import {
* Get error message from error object getErrorMessage as getErrorMessageShared,
*/ createLogError,
export function getErrorMessage(error: unknown): string { } from "../common.js";
return error instanceof Error ? error.message : "Unknown error";
} // Re-export shared utilities
export { getErrorMessageShared as getErrorMessage };
export const logError = createLogError(logger);

View File

@@ -5,7 +5,7 @@
import type { Request, Response } from "express"; import type { Request, Response } from "express";
import { getTerminalService } from "../../../services/terminal-service.js"; import { getTerminalService } from "../../../services/terminal-service.js";
import { getErrorMessage } from "../common.js"; import { getErrorMessage, logError } from "../common.js";
import { createLogger } from "../../../lib/logger.js"; import { createLogger } from "../../../lib/logger.js";
const logger = createLogger("Terminal"); const logger = createLogger("Terminal");
@@ -44,7 +44,7 @@ export function createSessionsCreateHandler() {
}, },
}); });
} catch (error) { } catch (error) {
logger.error("[Terminal] Error creating session:", error); logError(error, "Create terminal session failed");
res.status(500).json({ res.status(500).json({
success: false, success: false,
error: "Failed to create terminal session", error: "Failed to create terminal session",

View File

@@ -3,19 +3,13 @@
*/ */
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("Workspace"); const logger = createLogger("Workspace");
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}

View File

@@ -5,6 +5,10 @@
import { createLogger } from "../../lib/logger.js"; import { createLogger } from "../../lib/logger.js";
import { exec } from "child_process"; import { exec } from "child_process";
import { promisify } from "util"; import { promisify } from "util";
import {
getErrorMessage as getErrorMessageShared,
createLogError,
} from "../common.js";
const logger = createLogger("Worktree"); const logger = createLogger("Worktree");
const execAsync = promisify(exec); const execAsync = promisify(exec);
@@ -21,16 +25,6 @@ export async function isGitRepo(repoPath: string): Promise<boolean> {
} }
} }
/** // Re-export shared utilities
* Get error message from error object export { getErrorMessageShared as getErrorMessage };
*/ export const logError = createLogError(logger);
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}
/**
* Log error details consistently
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`, error);
}