/ src / utils / responses.js
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  }