exstack
Version:
A utility library designed to simplify and enhance Express.js applications.
881 lines (879 loc) • 29.5 kB
TypeScript
import { ErrorRequestHandler, NextFunction, Request, RequestHandler, Response, Router } from "express";
//#region src/enums.d.ts
/**
* Enum representing HTTP status codes.
*
* @publicApi http-status code
*/
declare const HttpStatus: Readonly<{
/** Continue with the request. */
CONTINUE: 100;
'100_NAME': "CONTINUE";
/** Switching protocols. */
SWITCHING_PROTOCOLS: 101;
'101_NAME': "SWITCHING_PROTOCOLS";
/** Request is being processed. */
PROCESSING: 102;
'102_NAME': "PROCESSING";
/** Early hints for the client. */
EARLYHINTS: 103;
'103_NAME': "EARLY_HINTS";
/** Request succeeded. */
OK: 200;
'200_NAME': "OK";
/** Resource created. */
CREATED: 201;
'201_NAME': "CREATED";
/** Request accepted for processing. */
ACCEPTED: 202;
'202_NAME': "ACCEPTED";
/** Non-authoritative information. */
NON_AUTHORITATIVE_INFORMATION: 203;
'203_NAME': "NON_AUTHORITATIVE_INFORMATION";
/** No content to send. */
NO_CONTENT: 204;
'204_NAME': "NO_CONTENT";
/** Content reset. */
RESET_CONTENT: 205;
'205_NAME': "RESET_CONTENT";
/** Partial content delivered. */
PARTIAL_CONTENT: 206;
'206_NAME': "PARTIAL_CONTENT";
/** Multiple choices available. */
AMBIGUOUS: 300;
'300_NAME': "AMBIGUOUS";
/** Resource moved permanently. */
MOVED_PERMANENTLY: 301;
'301_NAME': "MOVED_PERMANENTLY";
/** Resource found at another URI. */
FOUND: 302;
'302_NAME': "FOUND";
/** See other resource. */
SEE_OTHER: 303;
'303_NAME': "SEE_OTHER";
/** Resource not modified. */
NOT_MODIFIED: 304;
'304_NAME': "NOT_MODIFIED";
/** Temporary redirect. */
TEMPORARY_REDIRECT: 307;
'307_NAME': "TEMPORARY_REDIRECT";
/** Permanent redirect. */
PERMANENT_REDIRECT: 308;
'308_NAME': "PERMANENT_REDIRECT";
/** Bad request. */
BAD_REQUEST: 400;
'400_NAME': "BAD_REQUEST";
/** Authentication required. */
UNAUTHORIZED: 401;
'401_NAME': "UNAUTHORIZED";
/** Payment required. */
PAYMENT_REQUIRED: 402;
'402_NAME': "PAYMENT_REQUIRED";
/** Access forbidden. */
FORBIDDEN: 403;
'403_NAME': "FORBIDDEN";
/** Resource not found. */
NOT_FOUND: 404;
'404_NAME': "NOT_FOUND";
/** Method not allowed. */
METHOD_NOT_ALLOWED: 405;
'405_NAME': "METHOD_NOT_ALLOWED";
/** Not acceptable content. */
NOT_ACCEPTABLE: 406;
'406_NAME': "NOT_ACCEPTABLE";
/** Proxy authentication required. */
PROXY_AUTHENTICATION_REQUIRED: 407;
'407_NAME': "PROXY_AUTHENTICATION_REQUIRED";
/** Request timed out. */
REQUEST_TIMEOUT: 408;
'408_NAME': "REQUEST_TIMEOUT";
/** Conflict with current state. */
CONFLICT: 409;
'409_NAME': "CONFLICT";
/** Resource gone. */
GONE: 410;
'410_NAME': "GONE";
/** Length required. */
LENGTH_REQUIRED: 411;
'411_NAME': "LENGTH_REQUIRED";
/** Precondition failed. */
PRECONDITION_FAILED: 412;
'412_NAME': "PRECONDITION_FAILED";
/** Payload too large. */
PAYLOAD_TOO_LARGE: 413;
'413_NAME': "PAYLOAD_TOO_LARGE";
/** URI too long. */
URI_TOO_LONG: 414;
'414_NAME': "URI_TOO_LONG";
/** Unsupported media type. */
UNSUPPORTED_MEDIA_TYPE: 415;
'415_NAME': "UNSUPPORTED_MEDIA_TYPE";
/** Requested range not satisfiable. */
REQUESTED_RANGE_NOT_SATISFIABLE: 416;
'416_NAME': "REQUESTED_RANGE_NOT_SATISFIABLE";
/** Expectation failed. */
EXPECTATION_FAILED: 417;
'417_NAME': "EXPECTATION_FAILED";
/** I'm a teapot. */
I_AM_A_TEAPOT: 418;
'418_NAME': "I_AM_A_TEAPOT";
/** Misdirected request. */
MISDIRECTED: 421;
'421_NAME': "MISDIRECTED";
/** Unprocessable entity. */
UNPROCESSABLE_ENTITY: 422;
'422_NAME': "UNPROCESSABLE_ENTITY";
/** Locked. */
LOCKED: 423;
'423_NAME': "LOCKED";
/** Failed dependency. */
FAILED_DEPENDENCY: 424;
'424_NAME': "FAILED_DEPENDENCY";
/** Too early. */
TOO_EARLY: 425;
'425_NAME': "TOO_EARLY";
/** Upgrade required. */
UPGRADE_REQUIRED: 426;
'426_NAME': "UPGRADE_REQUIRED";
/** Precondition required. */
PRECONDITION_REQUIRED: 428;
'428_NAME': "PRECONDITION_REQUIRED";
/** Too many requests. */
TOO_MANY_REQUESTS: 429;
'429_NAME': "TOO_MANY_REQUESTS";
/** Request header fields too large. */
REQUEST_HEADER_FIELDS_TOO_LARGE: 431;
'431_NAME': "REQUEST_HEADER_FIELDS_TOO_LARGE";
/** Unavailable for legal reasons. */
UNAVAILABLE_FOR_LEGAL_REASONS: 451;
'451_NAME': "UNAVAILABLE_FOR_LEGAL_REASONS";
/** Internal server error. */
INTERNAL_SERVER_ERROR: 500;
'500_NAME': "INTERNAL_SERVER_ERROR";
/** Not implemented. */
NOT_IMPLEMENTED: 501;
'501_NAME': "NOT_IMPLEMENTED";
/** Bad gateway. */
BAD_GATEWAY: 502;
'502_NAME': "BAD_GATEWAY";
/** Service unavailable. */
SERVICE_UNAVAILABLE: 503;
'503_NAME': "SERVICE_UNAVAILABLE";
/** Gateway timeout. */
GATEWAY_TIMEOUT: 504;
'504_NAME': "GATEWAY_TIMEOUT";
/** HTTP version not supported. */
HTTP_VERSION_NOT_SUPPORTED: 505;
'505_NAME': "HTTP_VERSION_NOT_SUPPORTED";
/** Variant also negotiates. */
VARIANT_ALSO_NEGOTIATES: 506;
'506_NAME': "VARIANT_ALSO_NEGOTIATES";
/** Insufficient storage. */
INSUFFICIENT_STORAGE: 507;
'507_NAME': "INSUFFICIENT_STORAGE";
/** Loop detected. */
LOOP_DETECTED: 508;
'508_NAME': "LOOP_DETECTED";
/** Bandwidth limit exceeded. */
BANDWIDTH_LIMIT_EXCEEDED: 509;
'509_NAME': "BANDWIDTH_LIMIT_EXCEEDED";
/** Not extended. */
NOT_EXTENDED: 510;
'510_NAME': "NOT_EXTENDED";
/** Network authentication required. */
NETWORK_AUTHENTICATION_REQUIRED: 511;
'511_NAME': "NETWORK_AUTHENTICATION_REQUIRED";
}>;
//#endregion
//#region src/types.d.ts
/** Extracts the value type of an object */
type ValueOf<T> = T[keyof T];
/** Filters out only number types from a union */
type NumberOf<K> = Extract<K, number>;
type HttpStatusCode = NumberOf<ValueOf<typeof HttpStatus>>;
/**
* @module
* HTTP Status utility.
*/
type SuccessStatusCode = 100 | 101 | 102 | 103 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226;
type RedirectStatusCode = 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308;
type ServerErrorStatusCode = 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511;
type ClientErrorStatusCode = Exclude<HttpStatusCode, ServerErrorStatusCode | RedirectStatusCode | SuccessStatusCode>;
/**
* A generic type for request handler functions in an Express application.
*
* @example
* // Example usage for a login handler
* type LoginHandler = Handler<InputType<{ username: string; password: string }>>;
*/
type Handler<T extends InputType = any, R = any> = (req: Request<T['query'], any, T['body'], T['param']>, res: Response, next: NextFunction) => R;
/**
* A generic type for input validation schemas.
*
* @example
* // Example usage for a login input schema
* type LoginInput = InputType<{ username: string; password: string }>;
*/
type InputType<TBody = any, TParam = any, TQuery = any> = {
body: TBody;
query: TParam;
param: TQuery;
};
type Constructor<T> = new (...args: any[]) => T;
type WrappedMethods<T> = { [K in keyof T]: T[K] extends ((...args: any[]) => any) ? RequestHandler : T[K] };
//#endregion
//#region src/utils.d.ts
/**
* Express middleware to handle `HttpError` and unknown errors.
*
* - Sends JSON response for `HttpError` instances.
* - Logs unknown errors and sends generic error response.
* - Includes detailed error info in development (`isDev`).
*
* @param {Boolean} [isDev = true] - Flag to indicate if the environment is development.
* @param {(error: unknown) => void} [logger = console.error] - Function to log errors.
* @returns {ErrorRequestHandler} - Middleware for handling errors.
*
* @example
* // Basic usage with default options:
* app.use(errorHandler(process.env.NODE_ENV !== 'production'));
* // Custom usage with a logging function in production mode:
* app.use(errorHandler(conf.isDev, logger.error));
*/
declare const errorHandler: (isDev?: boolean, logger?: (error: unknown) => void) => ErrorRequestHandler;
/**
* Middleware to handle 404 Not Found errors.
*
* This function creates an Express router that catches all requests to
* undefined routes and returns a JSON response with a 404 error.
*
* @param {string} [path='*'] - The route pattern to match (default: '*').
* @returns {Router} Express router instance handling 404 errors.
*
* @example
* app.use(notFound())
*/
declare const notFound: (path?: string) => Router;
/** Map Action and subject with filter */
type MapObject<A extends readonly string[], S extends readonly string[], F extends Partial<Record<S[number], A[number][]>>> = Pick<{ [K in Uppercase<`${S[number]}_${A[number]}`>]: K extends `${infer Sub}_${infer Act}` ? `${Lowercase<Sub>}:${Lowercase<Act>}` : never }, Uppercase<`${Exclude<S[number], keyof F>}_${A[number]}`> | (keyof F extends infer FS ? FS extends S[number] ? F[FS] extends readonly A[number][] ? Uppercase<`${FS}_${F[FS][number]}`> : never : never : never)>;
/**
* Generates a permission object mapping subjects and actions to permission strings.
*
* @template A - List of actions that can be performed.
* @template S - List of subjects (resources) being acted upon.
* @template F - Optional object specifying which actions are allowed per subject.
*
* @param {Options<A, S, F>} options - The options object containing actions, subjects, and an optional filter.
* @returns {Readonly<PermissionMapping<A, S, F>>} A frozen object mapping subjects and actions to permission strings.
*
* @example
* const permissions = makePermission({
* actions: ['create', 'read', 'update', 'delete'] as const,
* subjects: ['user', 'post', 'comment'] as const,
* filter: {
* user: ['read'],
* post: ['create', 'update'],
* },
* });
* console.log(permissions.USER_CREATE);
*/
declare function makePermission<A extends readonly string[], S extends readonly string[], F extends Partial<Record<S[number], A[number][]>>>(options: {
actions: A;
subjects: S;
filter?: F;
}): Readonly<MapObject<A, S, F>>;
//#endregion
//#region src/errors.d.ts
/** The type for the body message of HTTP errors. */
type Message = string | string[];
/** The structure of the HTTP error body. */
type HttpErrorBody = {
data?: Record<string, unknown> | null;
code?: string | null;
error: string;
status: Status$1;
message: Message;
};
type Status$1 = ServerErrorStatusCode | ClientErrorStatusCode;
/**
* Get a human-readable error name from the HTTP status code.
* @param {number} status - The HTTP status code.
* @returns {string} - The formatted error name.
*/
declare const getErrorName: (status: Status$1) => string;
/**
* Base class for handling HTTP errors.
* @extends {Error}
*/
declare class HttpError extends Error {
readonly status: Status$1;
readonly options: Pick<HttpErrorBody, 'message' | 'data' | 'code'> & {
cause?: unknown;
};
/**
* Creates an instance of `HTTPException`.
* @param status - HTTP status code for the exception. Defaults to 500.
* @param options - Additional options for the exception.
*/
constructor(status: Status$1, options: Pick<HttpErrorBody, 'message' | 'data' | 'code'> & {
cause?: unknown;
});
/**
* Check if the given error is an instance of HttpError.
* @param {unknown} value - The error to check.
* @returns {boolean} - True if the error is an instance of HttpError, false otherwise.
*
* @example
* if (HttpError.isHttpError(error)) {
* // Handle the HttpError
* }
*/
static isHttpError: (value: unknown) => value is HttpError;
/**
* Convert the HttpError instance to a Body object.
* @example
* const errorBody = new HttpError(404, {message: 'Not Found'}).body;
*/
get body(): HttpErrorBody;
/**
* Send the json of the error in an HTTP response.
* @param {Response} res - The Express response object.
*
* @example
* new HttpError(404, {message: 'Not Found'}).toJson(res);
*/
toJson(res: Response): void;
}
/**
* Utility function to create custom error classes.
* @param status - HTTP status code.
* @returns - A new error class.
* @example
* const NotFoundError = createHttpErrorClass(HttpStatus.NOT_FOUND);
*/
declare const createHttpErrorClass: (status: Status$1) => {
new (message: Message, options?: {
cause?: unknown;
code?: string | null;
data?: Record<string, unknown> | null;
}): {
readonly status: Status$1;
readonly options: Pick<HttpErrorBody, "message" | "data" | "code"> & {
cause?: unknown;
};
/**
* Convert the HttpError instance to a Body object.
* @example
* const errorBody = new HttpError(404, {message: 'Not Found'}).body;
*/
readonly body: HttpErrorBody;
/**
* Send the json of the error in an HTTP response.
* @param {Response} res - The Express response object.
*
* @example
* new HttpError(404, {message: 'Not Found'}).toJson(res);
*/
toJson(res: Response): void;
name: string;
message: string;
stack?: string;
};
/**
* Check if the given error is an instance of HttpError.
* @param {unknown} value - The error to check.
* @returns {boolean} - True if the error is an instance of HttpError, false otherwise.
*
* @example
* if (HttpError.isHttpError(error)) {
* // Handle the HttpError
* }
*/
isHttpError: (value: unknown) => value is HttpError;
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
stackTraceLimit: number;
};
/**
* Represents a Bad Request HTTP error (400).
* @extends {HttpError}
*/
declare const BadRequestError: {
new (message: Message, options?: {
cause?: unknown;
code?: string | null;
data?: Record<string, unknown> | null;
}): {
readonly status: Status$1;
readonly options: Pick<HttpErrorBody, "message" | "data" | "code"> & {
cause?: unknown;
};
/**
* Convert the HttpError instance to a Body object.
* @example
* const errorBody = new HttpError(404, {message: 'Not Found'}).body;
*/
readonly body: HttpErrorBody;
/**
* Send the json of the error in an HTTP response.
* @param {Response} res - The Express response object.
*
* @example
* new HttpError(404, {message: 'Not Found'}).toJson(res);
*/
toJson(res: Response): void;
name: string;
message: string;
stack?: string;
};
/**
* Check if the given error is an instance of HttpError.
* @param {unknown} value - The error to check.
* @returns {boolean} - True if the error is an instance of HttpError, false otherwise.
*
* @example
* if (HttpError.isHttpError(error)) {
* // Handle the HttpError
* }
*/
isHttpError: (value: unknown) => value is HttpError;
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
stackTraceLimit: number;
};
/**
* Represents a Conflict HTTP error (409).
* @extends {HttpError}
*/
declare const ConflictError: {
new (message: Message, options?: {
cause?: unknown;
code?: string | null;
data?: Record<string, unknown> | null;
}): {
readonly status: Status$1;
readonly options: Pick<HttpErrorBody, "message" | "data" | "code"> & {
cause?: unknown;
};
/**
* Convert the HttpError instance to a Body object.
* @example
* const errorBody = new HttpError(404, {message: 'Not Found'}).body;
*/
readonly body: HttpErrorBody;
/**
* Send the json of the error in an HTTP response.
* @param {Response} res - The Express response object.
*
* @example
* new HttpError(404, {message: 'Not Found'}).toJson(res);
*/
toJson(res: Response): void;
name: string;
message: string;
stack?: string;
};
/**
* Check if the given error is an instance of HttpError.
* @param {unknown} value - The error to check.
* @returns {boolean} - True if the error is an instance of HttpError, false otherwise.
*
* @example
* if (HttpError.isHttpError(error)) {
* // Handle the HttpError
* }
*/
isHttpError: (value: unknown) => value is HttpError;
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
stackTraceLimit: number;
};
/**
* Represents a Forbidden HTTP error (403).
* @extends {HttpError}
*/
declare const ForbiddenError: {
new (message: Message, options?: {
cause?: unknown;
code?: string | null;
data?: Record<string, unknown> | null;
}): {
readonly status: Status$1;
readonly options: Pick<HttpErrorBody, "message" | "data" | "code"> & {
cause?: unknown;
};
/**
* Convert the HttpError instance to a Body object.
* @example
* const errorBody = new HttpError(404, {message: 'Not Found'}).body;
*/
readonly body: HttpErrorBody;
/**
* Send the json of the error in an HTTP response.
* @param {Response} res - The Express response object.
*
* @example
* new HttpError(404, {message: 'Not Found'}).toJson(res);
*/
toJson(res: Response): void;
name: string;
message: string;
stack?: string;
};
/**
* Check if the given error is an instance of HttpError.
* @param {unknown} value - The error to check.
* @returns {boolean} - True if the error is an instance of HttpError, false otherwise.
*
* @example
* if (HttpError.isHttpError(error)) {
* // Handle the HttpError
* }
*/
isHttpError: (value: unknown) => value is HttpError;
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
stackTraceLimit: number;
};
/**
* Represents a Not Found HTTP error (404).
* @extends {HttpError}
*/
declare const NotFoundError: {
new (message: Message, options?: {
cause?: unknown;
code?: string | null;
data?: Record<string, unknown> | null;
}): {
readonly status: Status$1;
readonly options: Pick<HttpErrorBody, "message" | "data" | "code"> & {
cause?: unknown;
};
/**
* Convert the HttpError instance to a Body object.
* @example
* const errorBody = new HttpError(404, {message: 'Not Found'}).body;
*/
readonly body: HttpErrorBody;
/**
* Send the json of the error in an HTTP response.
* @param {Response} res - The Express response object.
*
* @example
* new HttpError(404, {message: 'Not Found'}).toJson(res);
*/
toJson(res: Response): void;
name: string;
message: string;
stack?: string;
};
/**
* Check if the given error is an instance of HttpError.
* @param {unknown} value - The error to check.
* @returns {boolean} - True if the error is an instance of HttpError, false otherwise.
*
* @example
* if (HttpError.isHttpError(error)) {
* // Handle the HttpError
* }
*/
isHttpError: (value: unknown) => value is HttpError;
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
stackTraceLimit: number;
};
/**
* Represents an UnAuthorized HTTP error (401).
* @extends {HttpError}
*/
declare const UnAuthorizedError: {
new (message: Message, options?: {
cause?: unknown;
code?: string | null;
data?: Record<string, unknown> | null;
}): {
readonly status: Status$1;
readonly options: Pick<HttpErrorBody, "message" | "data" | "code"> & {
cause?: unknown;
};
/**
* Convert the HttpError instance to a Body object.
* @example
* const errorBody = new HttpError(404, {message: 'Not Found'}).body;
*/
readonly body: HttpErrorBody;
/**
* Send the json of the error in an HTTP response.
* @param {Response} res - The Express response object.
*
* @example
* new HttpError(404, {message: 'Not Found'}).toJson(res);
*/
toJson(res: Response): void;
name: string;
message: string;
stack?: string;
};
/**
* Check if the given error is an instance of HttpError.
* @param {unknown} value - The error to check.
* @returns {boolean} - True if the error is an instance of HttpError, false otherwise.
*
* @example
* if (HttpError.isHttpError(error)) {
* // Handle the HttpError
* }
*/
isHttpError: (value: unknown) => value is HttpError;
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
stackTraceLimit: number;
};
/**
* Represents an Internal Server Error HTTP error (500).
* @extends {HttpError}
*/
declare const InternalServerError: {
new (message: Message, options?: {
cause?: unknown;
code?: string | null;
data?: Record<string, unknown> | null;
}): {
readonly status: Status$1;
readonly options: Pick<HttpErrorBody, "message" | "data" | "code"> & {
cause?: unknown;
};
/**
* Convert the HttpError instance to a Body object.
* @example
* const errorBody = new HttpError(404, {message: 'Not Found'}).body;
*/
readonly body: HttpErrorBody;
/**
* Send the json of the error in an HTTP response.
* @param {Response} res - The Express response object.
*
* @example
* new HttpError(404, {message: 'Not Found'}).toJson(res);
*/
toJson(res: Response): void;
name: string;
message: string;
stack?: string;
};
/**
* Check if the given error is an instance of HttpError.
* @param {unknown} value - The error to check.
* @returns {boolean} - True if the error is an instance of HttpError, false otherwise.
*
* @example
* if (HttpError.isHttpError(error)) {
* // Handle the HttpError
* }
*/
isHttpError: (value: unknown) => value is HttpError;
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
stackTraceLimit: number;
};
/**
* Represents an Content Too Larger Error HTTP error (413).
* @extends {HttpError}
*/
declare const ContentTooLargeError: {
new (message: Message, options?: {
cause?: unknown;
code?: string | null;
data?: Record<string, unknown> | null;
}): {
readonly status: Status$1;
readonly options: Pick<HttpErrorBody, "message" | "data" | "code"> & {
cause?: unknown;
};
/**
* Convert the HttpError instance to a Body object.
* @example
* const errorBody = new HttpError(404, {message: 'Not Found'}).body;
*/
readonly body: HttpErrorBody;
/**
* Send the json of the error in an HTTP response.
* @param {Response} res - The Express response object.
*
* @example
* new HttpError(404, {message: 'Not Found'}).toJson(res);
*/
toJson(res: Response): void;
name: string;
message: string;
stack?: string;
};
/**
* Check if the given error is an instance of HttpError.
* @param {unknown} value - The error to check.
* @returns {boolean} - True if the error is an instance of HttpError, false otherwise.
*
* @example
* if (HttpError.isHttpError(error)) {
* // Handle the HttpError
* }
*/
isHttpError: (value: unknown) => value is HttpError;
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
stackTraceLimit: number;
};
//#endregion
//#region src/api-res.d.ts
type Status = Exclude<HttpStatusCode, ClientErrorStatusCode | ServerErrorStatusCode | RedirectStatusCode>;
/** The structure of the HTTP response body. */
type HttpResBody = {
result: any;
status: number;
message: string;
};
/**
* ApiRes class for standardizing API responses
*/
declare class ApiRes {
readonly result: any;
readonly status: Status;
readonly message: string;
/**
* Creates an instance of ApiRes.
* @param {any} result - The result of the operation
* @param {Status} status - The HTTP status code
* @param {string} message - The response message
*/
constructor(result?: any, status?: Status, message?: string);
/**
* Returns the Body (JSON) representation of the response.
* @returns The Body (JSON) representation of the response
*
* @example
* new ApiRes('Hello World', 200).body;
*/
get body(): HttpResBody;
/**
* Send the json of HTTP response.
* @param {Response} res - The Express response object.
*
* @example
* new ApiRes('Hello World', 200).toJson(res);
*/
toJson(res: Response): void;
/**
* Creates an OK (200) response.
* @param {any} result - The result to be included in the response
* @param {string} [message='Request processed successfully'] - The response message
* @returns {ApiRes} An ApiRes instance with OK status
*/
static ok: (result: any, message?: string) => ApiRes;
/**
* Creates a Created (201) response.
* @param {any} result - The result to be included in the response
* @param {string} [message='Resource created successfully'] - The response message
* @returns {ApiRes} An ApiRes instance with Created status
*/
static created: (result: any, message?: string) => ApiRes;
/**
* Creates a paginated OK (200) response.
* @param {any} data - The paginated data
* @param {object} meta - Metadata for pagination
* @param {string} [message='Data retrieved successfully'] - The response message
* @returns {ApiRes} An ApiRes instance with OK status and paginated data
*/
static paginated: (data: any, meta: object, message?: string) => ApiRes;
}
//#endregion
//#region src/handler.d.ts
/**
* Wraps an async route handler to manage errors and response handling.
*
* @param {Handler} callback - The route handler, which can return a value or a Promise.
* @returns {Handler} - A wrapped handler with error and result handling.
*
* @example
* // without type
* app.get('/example', handler(async () => await fetchData()));
* // with body type
* app.get('/example', handler<InputType<{name: string}>>(async req => await fetchData(req.body.name)));
* // with param type
* app.get('/example', handler<InputType<any, {name: string}>>(async req => await fetchData(req.param.name)));
* // with query type
* app.get('/example', handler<InputType<any, any, {name: string}>>(async req => await fetchData(req.query.name)));
*/
declare const handler: <I extends InputType>(callback: Handler<I, any | Promise<any>>) => Handler<I, Promise<void>>;
/**
* @param clsOrInstance - The class constructor or an instance of the class.
* @param args - The arguments for the class constructor.
* @returns A proxied instance where all methods are wrapped with `async-handler`.
*
* @example
* class MyClass {
* async myMethod() {
* return 'Hello, World!';
* }
* }
* const instance = proxyWrapper(MyClass);
*
* app.get("/", instance.myMethod)
*/
declare const proxyWrapper: {
/**
* Wraps a class constructor in a Proxy, allowing all methods to be
* automatically wrapped with `asyncHandler`.
*
* @param clsOrInstance - The class constructor.
* @returns A proxied instance where all methods are wrapped with `asyncHandler`.
*
* @example
* class MyClass {
* async myMethod() {
* return 'Hello, World!';
* }
* }
* const proxiedInstance = proxyWrapper(MyClass);
* await proxiedInstance.myMethod(); // Automatically wrapped with asyncHandler
*/
<T extends object>(clsOrInstance: Constructor<T>): WrappedMethods<T>;
/**
* Wraps an instance of a class in a Proxy, allowing all methods to be
* automatically wrapped with `asyncHandler`.
*
* @param clsOrInstance - An instance of the class.
* @returns A proxied instance where all methods are wrapped with `asyncHandler`.
*
* @example
* class MyClass {
* async myMethod() {
* return 'Hello, World!';
* }
* }
* const instance = new MyClass();
* const proxiedInstance = proxyWrapper(instance);
* await proxiedInstance.myMethod(); // Automatically wrapped with asyncHandler
*/
<T extends object>(clsOrInstance: T): WrappedMethods<T>;
/**
* Wraps a class constructor in a Proxy, allowing all methods to be
* automatically wrapped with `asyncHandler`, with constructor arguments.
*
* @param clsOrInstance - The class constructor.
* @param args - The arguments for the class constructor.
* @returns A proxied instance where all methods are wrapped with `asyncHandler`.
*
* @example
* class MyClass {
* constructor(private name: string) {}
* async greet() {
* return `Hello, ${this.name}!`;
* }
* }
* const proxiedInstance = proxyWrapper(MyClass, 'Alice');
* await proxiedInstance.greet(); // Automatically wrapped with asyncHandler
*/
<T extends object>(clsOrInstance: Constructor<T>, ...args: ConstructorParameters<Constructor<T>>): WrappedMethods<T>;
};
//#endregion
export { ApiRes, BadRequestError, ClientErrorStatusCode, ConflictError, Constructor, ContentTooLargeError, ForbiddenError, Handler, HttpError, HttpErrorBody, HttpResBody, HttpStatus, HttpStatusCode, InputType, InternalServerError, NotFoundError, NumberOf, RedirectStatusCode, ServerErrorStatusCode, SuccessStatusCode, UnAuthorizedError, ValueOf, WrappedMethods, createHttpErrorClass, errorHandler, getErrorName, handler, makePermission, notFound, proxyWrapper };