mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 12:22:14 +03:00
196 lines
4.6 KiB
TypeScript
196 lines
4.6 KiB
TypeScript
/**
|
|
* Error Codes Catalog — T-22
|
|
*
|
|
* Centralized error code registry for consistent API error responses.
|
|
* Each code has a category prefix, numeric ID, message, and HTTP status.
|
|
*
|
|
* Usage:
|
|
* import { ERROR_CODES, createErrorResponse } from "@/shared/constants/errorCodes";
|
|
* return createErrorResponse("AUTH_001", { detail: "Token expired" });
|
|
*
|
|
* @module shared/constants/errorCodes
|
|
*/
|
|
|
|
export interface ErrorCodeDef {
|
|
code: string;
|
|
message: string;
|
|
httpStatus: number;
|
|
category: string;
|
|
}
|
|
|
|
interface ErrorDetails {
|
|
detail?: string;
|
|
requestId?: string;
|
|
retryAfter?: number;
|
|
}
|
|
|
|
export const ERROR_CODES: Record<string, ErrorCodeDef> = {
|
|
// ── Auth ──
|
|
AUTH_001: {
|
|
code: "AUTH_001",
|
|
message: "Authentication required",
|
|
httpStatus: 401,
|
|
category: "AUTH",
|
|
},
|
|
AUTH_002: { code: "AUTH_002", message: "Invalid API key", httpStatus: 401, category: "AUTH" },
|
|
AUTH_003: { code: "AUTH_003", message: "API key expired", httpStatus: 401, category: "AUTH" },
|
|
AUTH_004: {
|
|
code: "AUTH_004",
|
|
message: "Insufficient permissions",
|
|
httpStatus: 403,
|
|
category: "AUTH",
|
|
},
|
|
AUTH_005: { code: "AUTH_005", message: "Account locked", httpStatus: 423, category: "AUTH" },
|
|
AUTH_006: {
|
|
code: "AUTH_006",
|
|
message: "No credentials for provider",
|
|
httpStatus: 400,
|
|
category: "AUTH",
|
|
},
|
|
|
|
// ── Proxy ──
|
|
PROXY_001: {
|
|
code: "PROXY_001",
|
|
message: "Proxy connection failed",
|
|
httpStatus: 502,
|
|
category: "PROXY",
|
|
},
|
|
PROXY_002: { code: "PROXY_002", message: "Proxy timeout", httpStatus: 504, category: "PROXY" },
|
|
PROXY_003: {
|
|
code: "PROXY_003",
|
|
message: "All proxies exhausted",
|
|
httpStatus: 503,
|
|
category: "PROXY",
|
|
},
|
|
|
|
// ── Rate Limiting ──
|
|
RATE_001: {
|
|
code: "RATE_001",
|
|
message: "Rate limit exceeded",
|
|
httpStatus: 429,
|
|
category: "RATE_LIMIT",
|
|
},
|
|
RATE_002: {
|
|
code: "RATE_002",
|
|
message: "Daily budget exceeded",
|
|
httpStatus: 429,
|
|
category: "RATE_LIMIT",
|
|
},
|
|
RATE_003: {
|
|
code: "RATE_003",
|
|
message: "All accounts rate-limited",
|
|
httpStatus: 503,
|
|
category: "RATE_LIMIT",
|
|
},
|
|
|
|
// ── Model / Routing ──
|
|
MODEL_001: { code: "MODEL_001", message: "Model not found", httpStatus: 404, category: "MODEL" },
|
|
MODEL_002: {
|
|
code: "MODEL_002",
|
|
message: "Ambiguous model identifier",
|
|
httpStatus: 400,
|
|
category: "MODEL",
|
|
},
|
|
MODEL_003: {
|
|
code: "MODEL_003",
|
|
message: "Model temporarily unavailable",
|
|
httpStatus: 503,
|
|
category: "MODEL",
|
|
},
|
|
|
|
// ── Provider ──
|
|
PROVIDER_001: {
|
|
code: "PROVIDER_001",
|
|
message: "Provider error",
|
|
httpStatus: 502,
|
|
category: "PROVIDER",
|
|
},
|
|
PROVIDER_002: {
|
|
code: "PROVIDER_002",
|
|
message: "Provider timeout",
|
|
httpStatus: 504,
|
|
category: "PROVIDER",
|
|
},
|
|
PROVIDER_003: {
|
|
code: "PROVIDER_003",
|
|
message: "Provider not configured",
|
|
httpStatus: 400,
|
|
category: "PROVIDER",
|
|
},
|
|
|
|
// ── Validation ──
|
|
VALID_001: {
|
|
code: "VALID_001",
|
|
message: "Invalid request body",
|
|
httpStatus: 400,
|
|
category: "VALIDATION",
|
|
},
|
|
VALID_002: {
|
|
code: "VALID_002",
|
|
message: "Missing required field",
|
|
httpStatus: 400,
|
|
category: "VALIDATION",
|
|
},
|
|
VALID_003: {
|
|
code: "VALID_003",
|
|
message: "Input sanitization blocked",
|
|
httpStatus: 400,
|
|
category: "VALIDATION",
|
|
},
|
|
|
|
// ── Internal ──
|
|
INTERNAL_001: {
|
|
code: "INTERNAL_001",
|
|
message: "Internal server error",
|
|
httpStatus: 500,
|
|
category: "INTERNAL",
|
|
},
|
|
INTERNAL_002: {
|
|
code: "INTERNAL_002",
|
|
message: "Database error",
|
|
httpStatus: 500,
|
|
category: "INTERNAL",
|
|
},
|
|
INTERNAL_003: {
|
|
code: "INTERNAL_003",
|
|
message: "Circuit breaker open",
|
|
httpStatus: 503,
|
|
category: "INTERNAL",
|
|
},
|
|
};
|
|
|
|
export function createErrorResponse(code: string, details: ErrorDetails = {}) {
|
|
const def = ERROR_CODES[code];
|
|
if (!def) {
|
|
return {
|
|
error: {
|
|
code: "INTERNAL_001",
|
|
message: `Unknown error code: ${code}`,
|
|
category: "INTERNAL",
|
|
},
|
|
status: 500,
|
|
};
|
|
}
|
|
|
|
const response: any = {
|
|
error: {
|
|
code: def.code,
|
|
message: def.message,
|
|
category: def.category,
|
|
...(details.detail ? { detail: details.detail } : {}),
|
|
...(details.requestId ? { requestId: details.requestId } : {}),
|
|
},
|
|
status: def.httpStatus,
|
|
};
|
|
|
|
if (details.retryAfter) {
|
|
response.retryAfter = details.retryAfter;
|
|
}
|
|
|
|
return response;
|
|
}
|
|
|
|
export function getErrorsByCategory(category: string): ErrorCodeDef[] {
|
|
return Object.values(ERROR_CODES).filter((e) => e.category === category);
|
|
}
|