- isAlreadyExistsError를 pointService에서 middleware/errors로 이동 — 레포지토리가 서비스를 import하는 계층 역전 없이 양쪽에서 쓰기 위함. pointService는 re-export로 기존 호출부 호환 유지 - createOrder에서 getWalletTx 사전 호출과 잔액 사전 검사 제거 — applyPointChangesTx가 같은 트랜잭션에서 동일한 HttpError(409, INSUFFICIENT_BALANCE)를 던지므로 동작은 같고 wallet 문서 tx.get이 2회에서 1회로 준다
36 lines
1.1 KiB
TypeScript
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 });
|
|
}
|