import type { Request, Response } from "express"; import { ProjectHistoryOperationUnavailableError } from "../../domain/errors/project-history-operation-unavailable.error.js"; import { ProjectRevisionConflictError } from "../../domain/errors/project-revision-conflict.error.js"; import { executeProjectCommandSchema, executeProjectHistoryCommandSchema, } from "../../shared/validation/project-command.schemas.js"; import { projectCommandService } from "../composition/project-command-stores.js"; export function executeProjectCommand(req: Request, res: Response) { const projectId = getProjectId(req, res); if (!projectId) { return; } const parsed = executeProjectCommandSchema.safeParse(req.body); if (!parsed.success) { return res.status(400).json({ error: parsed.error.flatten() }); } try { return res.json( projectCommandService.executeUser({ projectId, ...parsed.data, }) ); } catch (error) { return respondWithProjectCommandError(error, res); } } export function undoProjectCommand(req: Request, res: Response) { return executeHistoryCommand(req, res, "undo"); } export function redoProjectCommand(req: Request, res: Response) { return executeHistoryCommand(req, res, "redo"); } function executeHistoryCommand( req: Request, res: Response, direction: "undo" | "redo" ) { const projectId = getProjectId(req, res); if (!projectId) { return; } const parsed = executeProjectHistoryCommandSchema.safeParse(req.body); if (!parsed.success) { return res.status(400).json({ error: parsed.error.flatten() }); } try { const result = projectCommandService[direction]({ projectId, ...parsed.data, }); return res.json(result); } catch (error) { return respondWithProjectCommandError(error, res); } } function getProjectId(req: Request, res: Response) { const { projectId } = req.params; if (typeof projectId !== "string" || !projectId.trim()) { res.status(400).json({ error: "Invalid projectId" }); return null; } return projectId; } export function respondWithProjectCommandError( error: unknown, res: Response ) { if (error instanceof ProjectRevisionConflictError) { return res.status(409).json({ error: error.message, code: "PROJECT_REVISION_CONFLICT", expectedRevision: error.expectedRevision, currentRevision: error.actualRevision, }); } if (error instanceof ProjectHistoryOperationUnavailableError) { return res.status(409).json({ error: error.message, code: "PROJECT_HISTORY_OPERATION_UNAVAILABLE", direction: error.direction, }); } return res.status(400).json({ error: error instanceof Error ? error.message : "Project command could not be executed.", }); }