responses.js
1 import { sanitizeObject } from "./sanitizer.js"; 2 3 export function successResponse(data = null, message = null, meta = null) { 4 const response = { 5 success: true, 6 }; 7 8 if (message) { 9 response.message = typeof message === "string" && message.length > 500 ? message.substring(0, 500) + "..." : message; 10 } 11 if (data !== null) { 12 response.data = sanitizeObject(data); 13 } 14 if (meta) { 15 response.meta = sanitizeObject(meta); 16 } 17 18 return response; 19 } 20 21 export function errorResponse(error, message, details = null, _statusCode = null) { 22 const sanitizedError = typeof error === "string" && error.length > 500 ? error.substring(0, 500) + "..." : error; 23 const sanitizedMessage = typeof message === "string" && message.length > 500 ? message.substring(0, 500) + "..." : message; 24 25 const response = { 26 success: false, 27 error: sanitizedError, 28 message: sanitizedMessage, 29 }; 30 31 if (details !== null) { 32 response.details = sanitizeObject(details); 33 } 34 35 return response; 36 } 37 38 export function validationErrorResponse(errors, message = "Validation failed") { 39 const sanitizedErrors = Array.isArray(errors) ? errors.map(err => { 40 if (typeof err === "string") { 41 return err.length > 500 ? err.substring(0, 500) + "..." : err; 42 } else if (typeof err === "object" && err !== null) { 43 return sanitizeObject(err, 0, 2); 44 } else { 45 return err; 46 } 47 }) : [sanitizeObject(errors, 0, 2)]; 48 49 return { 50 success: false, 51 error: "validation_error", 52 message: typeof message === "string" && message.length > 500 ? message.substring(0, 500) + "..." : message, 53 details: { 54 errors: sanitizedErrors, 55 }, 56 }; 57 } 58 59 export function paginatedResponse(items, page, limit, total, message = null) { 60 const totalPages = Math.ceil(total / limit); 61 return { 62 success: true, 63 message: typeof message === "string" && message.length > 500 ? message.substring(0, 500) + "..." : message, 64 data: sanitizeObject(items), 65 meta: { 66 pagination: { 67 page, 68 limit, 69 total, 70 totalPages, 71 hasNext: page < totalPages, 72 hasPrev: page > 1, 73 }, 74 }, 75 }; 76 } 77 78 export const ErrorCodes = { 79 UNAUTHORIZED: "unauthorized", 80 FORBIDDEN: "forbidden", 81 INVALID_TOKEN: "invalid_token", 82 TOKEN_EXPIRED: "token_expired", 83 INVALID_CREDENTIALS: "invalid_credentials", 84 SESSION_EXPIRED: "session_expired", 85 VALIDATION_ERROR: "validation_error", 86 INVALID_INPUT: "invalid_input", 87 INVALID_REQUEST: "invalid_request", 88 MISSING_REQUIRED_FIELD: "missing_required_field", 89 INVALID_FORMAT: "invalid_format", 90 NOT_FOUND: "not_found", 91 ALREADY_EXISTS: "already_exists", 92 CONFLICT: "conflict", 93 OPERATION_FAILED: "operation_failed", 94 INSUFFICIENT_FUNDS: "insufficient_funds", 95 TRANSACTION_FAILED: "transaction_failed", 96 NETWORK_ERROR: "network_error", 97 LIMIT_EXCEEDED: "limit_exceeded", 98 INTERNAL_ERROR: "internal_error", 99 SERVICE_UNAVAILABLE: "service_unavailable", 100 DATABASE_ERROR: "database_error", 101 TOO_MANY_REQUESTS: "too_many_requests", 102 PASSWORD_REQUIRED: "password_required", 103 PAYLOAD_TOO_LARGE: "payload_too_large", 104 }; 105 106 export const StatusCodes = { 107 OK: 200, 108 CREATED: 201, 109 ACCEPTED: 202, 110 NO_CONTENT: 204, 111 BAD_REQUEST: 400, 112 UNAUTHORIZED: 401, 113 FORBIDDEN: 403, 114 NOT_FOUND: 404, 115 CONFLICT: 409, 116 UNPROCESSABLE_ENTITY: 422, 117 TOO_MANY_REQUESTS: 429, 118 REQUEST_TOO_LARGE: 413, 119 INTERNAL_SERVER_ERROR: 500, 120 SERVICE_UNAVAILABLE: 503, 121 }; 122 123 export function sendSuccess(res, data = null, message = null, statusCode = StatusCodes.OK) { 124 return res.status(statusCode).json(successResponse(data, message)); 125 } 126 127 export function sendError(res, error, message, statusCode = StatusCodes.BAD_REQUEST, details = null) { 128 return res.status(statusCode).json(errorResponse(error, message, details, statusCode)); 129 } 130 131 export function sendValidationError(res, errors, message = "Validation failed") { 132 return res.status(StatusCodes.UNPROCESSABLE_ENTITY).json(validationErrorResponse(errors, message)); 133 } 134 135 export function serviceResponse(success, data = null, error = null, message = null) { 136 if (success) { 137 return { 138 success: true, 139 data, 140 message, 141 }; 142 } 143 return { 144 success: false, 145 error: error || ErrorCodes.OPERATION_FAILED, 146 message: message || "Operation failed", 147 data, 148 }; 149 } 150 151 export function getClientInfo(req) { 152 return { 153 ipAddress: req.ip || req.headers["x-forwarded-for"] || req.connection?.remoteAddress, 154 userAgent: req.headers["user-agent"], 155 }; 156 }