fix: standardize error classes in shared service modules
Replace raw `Error` with `UserError` for user-facing conditions (invalid trade state, user not found, permission/channel type checks) and `SystemError` for internal failures (DB insert failures, external API errors, missing config). Improves Discord UX by ensuring user-facing errors are surfaced cleanly via withCommandErrorHandling. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import { itemTransactions } from "@db/schema";
|
||||
import { withTransaction } from "@/lib/db";
|
||||
import type { Transaction } from "@shared/lib/types";
|
||||
import { TransactionType, ItemTransactionType } from "@shared/lib/constants";
|
||||
import { UserError } from "@shared/lib/errors";
|
||||
|
||||
// Module-level session storage
|
||||
const sessions = new Map<string, TradeSession>();
|
||||
@@ -114,11 +115,11 @@ export const tradeService = {
|
||||
*/
|
||||
updateMoney: (threadId: string, userId: string, amount: bigint) => {
|
||||
const session = tradeService.getSession(threadId);
|
||||
if (!session) throw new Error("Session not found");
|
||||
if (session.state !== 'NEGOTIATING') throw new Error("Trade is not active");
|
||||
if (!session) throw new UserError("Session not found");
|
||||
if (session.state !== 'NEGOTIATING') throw new UserError("Trade is not active");
|
||||
|
||||
const participant = session.userA.id === userId ? session.userA : session.userB.id === userId ? session.userB : null;
|
||||
if (!participant) throw new Error("User not in trade");
|
||||
if (!participant) throw new UserError("User not in trade");
|
||||
|
||||
participant.offer.money = amount;
|
||||
unlockAll(session);
|
||||
@@ -127,11 +128,11 @@ export const tradeService = {
|
||||
|
||||
addItem: (threadId: string, userId: string, item: { id: number, name: string }, quantity: bigint) => {
|
||||
const session = tradeService.getSession(threadId);
|
||||
if (!session) throw new Error("Session not found");
|
||||
if (session.state !== 'NEGOTIATING') throw new Error("Trade is not active");
|
||||
if (!session) throw new UserError("Session not found");
|
||||
if (session.state !== 'NEGOTIATING') throw new UserError("Trade is not active");
|
||||
|
||||
const participant = session.userA.id === userId ? session.userA : session.userB.id === userId ? session.userB : null;
|
||||
if (!participant) throw new Error("User not in trade");
|
||||
if (!participant) throw new UserError("User not in trade");
|
||||
|
||||
const existing = participant.offer.items.find(i => i.id === item.id);
|
||||
if (existing) {
|
||||
@@ -146,10 +147,10 @@ export const tradeService = {
|
||||
|
||||
removeItem: (threadId: string, userId: string, itemId: number) => {
|
||||
const session = tradeService.getSession(threadId);
|
||||
if (!session) throw new Error("Session not found");
|
||||
if (!session) throw new UserError("Session not found");
|
||||
|
||||
const participant = session.userA.id === userId ? session.userA : session.userB.id === userId ? session.userB : null;
|
||||
if (!participant) throw new Error("User not in trade");
|
||||
if (!participant) throw new UserError("User not in trade");
|
||||
|
||||
participant.offer.items = participant.offer.items.filter(i => i.id !== itemId);
|
||||
|
||||
@@ -159,10 +160,10 @@ export const tradeService = {
|
||||
|
||||
toggleLock: (threadId: string, userId: string): boolean => {
|
||||
const session = tradeService.getSession(threadId);
|
||||
if (!session) throw new Error("Session not found");
|
||||
if (!session) throw new UserError("Session not found");
|
||||
|
||||
const participant = session.userA.id === userId ? session.userA : session.userB.id === userId ? session.userB : null;
|
||||
if (!participant) throw new Error("User not in trade");
|
||||
if (!participant) throw new UserError("User not in trade");
|
||||
|
||||
participant.locked = !participant.locked;
|
||||
session.lastInteraction = Date.now();
|
||||
@@ -179,10 +180,10 @@ export const tradeService = {
|
||||
*/
|
||||
executeTrade: async (threadId: string): Promise<void> => {
|
||||
const session = tradeService.getSession(threadId);
|
||||
if (!session) throw new Error("Session not found");
|
||||
if (!session) throw new UserError("Session not found");
|
||||
|
||||
if (!session.userA.locked || !session.userB.locked) {
|
||||
throw new Error("Both players must accept the trade first.");
|
||||
throw new UserError("Both players must accept the trade first.");
|
||||
}
|
||||
|
||||
session.state = 'COMPLETED'; // Prevent double execution
|
||||
|
||||
Reference in New Issue
Block a user