윤정민 aa53a5b070 Extract ALREADY_EXISTS guard and drop duplicate wallet read
- isAlreadyExistsError를 pointService에서 middleware/errors로 이동 — 레포지토리가 서비스를 import하는 계층 역전 없이 양쪽에서 쓰기 위함. pointService는 re-export로 기존 호출부 호환 유지
- createOrder에서 getWalletTx 사전 호출과 잔액 사전 검사 제거 — applyPointChangesTx가 같은 트랜잭션에서 동일한 HttpError(409, INSUFFICIENT_BALANCE)를 던지므로 동작은 같고 wallet 문서 tx.get이 2회에서 1회로 준다
2026-07-27 13:24:35 +09:00

36 lines
1.1 KiB
TypeScript

import type express from "express";
export class HttpError extends Error {
constructor(
public status: number,
message: string,
public code?: string,
public details?: Record<string, unknown>
) {
super(message);
}
}
/**
* Firestore ALREADY_EXISTS 판별 — `create()`를 멱등 쓰기로 쓰는 경로에서
* "이미 존재"를 정상 분기로 처리하기 위한 것. 레포지토리·서비스 양쪽이 쓰므로
* 계층 역전이 없는 여기에 둔다.
*/
export function isAlreadyExistsError(err: unknown): boolean {
const code = (err as { code?: unknown })?.code;
return code === 6 || code === "already-exists" || code === "ALREADY_EXISTS";
}
export function sendError(res: express.Response, err: unknown): void {
if (err instanceof HttpError) {
const body: Record<string, unknown> = err.code
? { error: err.code, message: err.message }
: { error: err.message };
if (err.details) Object.assign(body, err.details);
res.status(err.status).json(body);
return;
}
const message = err instanceof Error ? err.message : String(err);
res.status(500).json({ error: message });
}