UNPKG

@catbee/utils

Version:

A modular, production-grade utility toolkit for Node.js and TypeScript, designed for robust, scalable applications (including Express-based services). All utilities are tree-shakable and can be imported independently.

233 lines 9.21 kB
var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); import { randomUUID } from "crypto"; import { getRequestId } from "./context-store.utils"; /** * Standard HTTP response wrapper for successful responses. * Implements the `ApiResponse<T>` interface and sets default values. * * @typeParam T - The shape of the data returned in the response. */ var SuccessResponse = /** @class */ (function () { /** * Constructs a new success response. * * @param {string} message - Optional message to override the default. * @param {T} [data] - Optional data payload. */ function SuccessResponse(message, data) { var _a; /** Message describing the result of the operation. */ this.message = "Success"; /** Whether the response is an error. Always false in success responses. */ this.error = false; /** The payload returned from the API. */ this.data = null; /** Timestamp when the response was generated, in ISO format. */ this.timestamp = new Date().toISOString(); /** Unique identifier for this response, useful for request tracing. */ this.requestId = (_a = getRequestId()) !== null && _a !== void 0 ? _a : randomUUID(); if (message) this.message = message; this.data = data !== null && data !== void 0 ? data : null; } return SuccessResponse; }()); export { SuccessResponse }; /** * Wrapper for error responses that extends the native `Error` object. * Implements `ApiResponse` but omits the `data` field (which should not be present in errors). */ var ErrorResponse = /** @class */ (function (_super) { __extends(ErrorResponse, _super); /** * Constructs a new error response. * * @param {string} message - The error message to display or log. * @param {number} [status=500] - Optional HTTP status code (defaults to 500). */ function ErrorResponse(message, status) { if (status === void 0) { status = 500; } var _a; var _this = _super.call(this, message) || this; /** Indicates that this is an error. Always true. */ _this.error = true; /** Timestamp when the error occurred, in ISO format. */ _this.timestamp = new Date().toISOString(); /** Unique identifier for this error instance. */ _this.requestId = (_a = getRequestId()) !== null && _a !== void 0 ? _a : randomUUID(); _this.status = status; _this.name = _this.constructor.name; Error.captureStackTrace(_this, _this.constructor); return _this; } return ErrorResponse; }(Error)); export { ErrorResponse }; /** * Response with paginated data extending the standard success response. * Useful for APIs that return large collections of data. * * @typeParam T - The shape of each item in the paginated collection. */ var PaginatedResponse = /** @class */ (function (_super) { __extends(PaginatedResponse, _super); /** * Constructs a new paginated response. * * @param {T[]} items - The current page of items. * @param {Object} pagination - Pagination information. * @param {number} pagination.total - Total number of items across all pages. * @param {number} pagination.page - Current page number (1-based). * @param {number} pagination.pageSize - Number of items per page. * @param {string} [message="Success"] - Optional custom message. */ function PaginatedResponse(items, pagination, message) { if (message === void 0) { message = "Success"; } var _this = _super.call(this, message, items) || this; _this.total = pagination.total; _this.page = pagination.page; _this.pageSize = pagination.pageSize; _this.totalPages = Math.ceil(_this.total / _this.pageSize); _this.hasNext = _this.page < _this.totalPages; _this.hasPrevious = _this.page > 1; return _this; } return PaginatedResponse; }(SuccessResponse)); export { PaginatedResponse }; /** * Specialized response for operations that don't return data (HTTP 204). */ var NoContentResponse = /** @class */ (function (_super) { __extends(NoContentResponse, _super); /** * Constructs a new no-content response. * * @param {string} [message="Operation completed successfully"] - Optional custom message. */ function NoContentResponse(message) { if (message === void 0) { message = "Operation completed successfully"; } return _super.call(this, message, null) || this; } return NoContentResponse; }(SuccessResponse)); export { NoContentResponse }; /** * Specialized response for redirects. */ var RedirectResponse = /** @class */ (function () { /** * Constructs a new redirect response. * * @param {string} url - The URL to redirect to. * @param {number} [statusCode=302] - HTTP status code for the redirect. */ function RedirectResponse(url, statusCode) { if (statusCode === void 0) { statusCode = 302; } var _a; /** Whether the response is a redirect */ this.isRedirect = true; /** Unique identifier for this response */ this.requestId = (_a = getRequestId()) !== null && _a !== void 0 ? _a : randomUUID(); this.redirectUrl = url; this.statusCode = statusCode; } return RedirectResponse; }()); export { RedirectResponse }; /** * Creates a standard success response. * * @typeParam T - The shape of the data returned in the response. * @param {T} data - The data to include in the response. * @param {string} [message="Success"] - Optional custom message. * @returns {SuccessResponse<T>} A properly formatted success response. */ export function createSuccessResponse(data, message) { if (message === void 0) { message = "Success"; } return new SuccessResponse(message, data); } /** * Creates a standard error response. * * @param {string} message - The error message. * @param {number} [statusCode=500] - HTTP status code for the error. * @returns {ErrorResponse} A properly formatted error response. */ export function createErrorResponse(message, statusCode) { if (statusCode === void 0) { statusCode = 500; } return new ErrorResponse(message, statusCode); } /** * Creates a paginated response from array data. * * @typeParam T - The shape of each item in the collection. * @param {T[]} allItems - The complete array of items to paginate. * @param {number} page - The requested page (1-based). * @param {number} pageSize - The number of items per page. * @param {string} [message="Success"] - Optional custom message. * @returns {PaginatedResponse<T>} A properly formatted paginated response. */ export function createPaginatedResponse(allItems, page, pageSize, message) { if (message === void 0) { message = "Success"; } // Ensure valid pagination parameters var validPage = Math.max(1, page); var validPageSize = Math.max(1, pageSize); // Calculate slice indices var startIndex = (validPage - 1) * validPageSize; var endIndex = startIndex + validPageSize; // Get current page items var pageItems = allItems.slice(startIndex, endIndex); return new PaginatedResponse(pageItems, { total: allItems.length, page: validPage, pageSize: validPageSize, }, message); } /** * Adapter to convert API responses to Express.js response format. * * @param {any} res - Express response object. * @param {SuccessResponse<any> | ErrorResponse | RedirectResponse} apiResponse - API response instance. */ export function sendResponse(res, apiResponse) { // Handle redirects if ("redirectUrl" in apiResponse) { res.redirect(apiResponse.statusCode, apiResponse.redirectUrl); return; } // Handle errors if ("error" in apiResponse && apiResponse.error) { var errorResponse = apiResponse; res.status(errorResponse.status).json({ error: true, message: errorResponse.message, timestamp: errorResponse.timestamp, requestId: errorResponse.requestId, }); return; } // Handle success responses var successResponse = apiResponse; // No content (204) shouldn't return a body if (successResponse instanceof NoContentResponse) { res.status(204).end(); return; } res.status(200).json(successResponse); } //# sourceMappingURL=response.utils.js.map