Skip to content

Commit

Permalink
fix: fix response handling methods:
Browse files Browse the repository at this point in the history
  • Loading branch information
teclone committed Feb 11, 2024
1 parent 1ef4686 commit d7a1273
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 52 deletions.
4 changes: 2 additions & 2 deletions src/@types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ export interface RouteResponse<Data = {}, Errors = {}> {
headers?: IncomingHttpHeaders;
}

export interface APIExecutor<RequestBody, ResponseData> {
export interface APIExecutor<RequestBody, Data, Errors = {}> {
(arg: {
/**
* request body, should be a combination of parsed post body and url search params
Expand All @@ -261,7 +261,7 @@ export interface APIExecutor<RequestBody, ResponseData> {
* request path parameters, as contained in the routing path
*/
pathParams: PathParameters;
}): Promise<RouteResponse<ResponseData> | null>;
}): Promise<RouteResponse<Data, Errors> | null>;

/**
* assigned name of the handler
Expand Down
108 changes: 58 additions & 50 deletions src/modules/Response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ import { ErrorCallback, RouteResponse } from '../@types';
import { handleError } from './Utils';
import { ServerRequest } from './Request';

export interface AfterResponseCallbacksOpt<Data, Errors> {
/**
* handler callback after a successful response has been sent to the client
*/
onSuccess?: (response: RouteResponse<Data, Errors>) => void;

/**
* callback is called after an error response is sent back to the client
*/
onError?: (response: RouteResponse<Data, Errors>) => void;
}

export type ServerResponse<
T extends typeof Http2ServerResponse | typeof Http1ServerResponse =
| typeof Http2ServerResponse
Expand Down Expand Up @@ -99,6 +111,7 @@ export type ServerResponse<
path: string,
status?: number
): Promise<boolean>;

/**
* sends a file download attachment to the client
* @param filePath - relative or absolute file path
Expand All @@ -113,17 +126,19 @@ export type ServerResponse<
/**
* sends json error data back to the client
*/
jsonError(
jsonError<Data, Errors>(
this: ServerResponse<T>,
response?: RouteResponse
response?: RouteResponse<Data, Errors>,
options?: AfterResponseCallbacksOpt<Data, Errors>
): Promise<boolean>;

/**
* sends json success data back to the client
*/
jsonSuccess(
jsonSuccess<Data, Errors>(
this: ServerResponse<T>,
response?: RouteResponse
response?: RouteResponse<Data, Errors>,
options?: AfterResponseCallbacksOpt<Data, Errors>
): Promise<boolean>;

/**
Expand All @@ -139,11 +154,13 @@ export type ServerResponse<
*/
processRouteResponse<Data, Errors>(
this: ServerResponse<T>,

/**
* the response promise
*/
responsePromise: Promise<RouteResponse<Data, Errors>>,
options?: {
onSuccess?: (response: RouteResponse<Data, Errors>) => void;
onError?: (response: RouteResponse<Data, Errors>) => void;
}

options?: AfterResponseCallbacksOpt<Data, Errors>
): Promise<boolean>;
};

Expand Down Expand Up @@ -223,75 +240,71 @@ const createResponseClass = <
return this;
};

ResponseClass.prototype.removeHeaders = function (...names: string[]) {
ResponseClass.prototype.removeHeaders = function (...names) {
names.forEach((name) => {
this.removeHeader(name);
});
return this;
};

ResponseClass.prototype.status = function (code: number) {
ResponseClass.prototype.status = function (code) {
this.statusCode = code;
return this;
};

ResponseClass.prototype.redirect = function (
path: string,
status = 302
): Promise<boolean> {
ResponseClass.prototype.redirect = function (path, status = 302) {
return this.status(status).setHeader('Location', path).end();
};

ResponseClass.prototype.download = function (
filePath: string,
filename?: string
): Promise<boolean> {
ResponseClass.prototype.download = function (filePath, filename) {
return this.fileServer.serveDownload(filePath, this, filename);
};

ResponseClass.prototype.json = function (
data?: object | string
): Promise<boolean> {
ResponseClass.prototype.json = function (data) {
const resolvedData =
typeof data === 'string' ? data : JSON.stringify(data || '');
return this.setHeader('Content-Type', 'application/json').end(resolvedData);
};

ResponseClass.prototype.jsonError = function (
response?: RouteResponse
): Promise<boolean> {
const {
statusCode = 400,
headers,
message,
errors = null,
} = response || {};

if (statusCode < 300) {
return this.jsonSuccess(response);
}
ResponseClass.prototype.jsonError = function (response, opts) {
const { headers, message, errors = null, statusCode } = response || {};

return this.status(statusCode)
return this.status(statusCode || 400)
.setHeaders(headers)
.json({
message: message || 'Request failed',
errors,
})
.finally(() => {
if (opts?.onError) {
opts.onError(response);
}
});
};

ResponseClass.prototype.jsonSuccess = function (
response?: RouteResponse
): Promise<boolean> {
const { statusCode = 200, headers, message, data = null } = response || {};
if (statusCode >= 300) {
return this.jsonError(response);
ResponseClass.prototype.jsonSuccess = function (response, opts) {
const {
statusCode = 200,
headers,
message,
data = null,
errors,
} = response || {};

if (statusCode >= 300 || errors) {
return this.jsonError(response, opts);
}

return this.status(statusCode)
.setHeaders(headers)
.json({
message: message || 'Request successful',
data,
})
.finally(() => {
if (opts?.onSuccess) {
opts.onSuccess(response);
}
});
};

Expand All @@ -305,23 +318,18 @@ const createResponseClass = <

ResponseClass.prototype.processRouteResponse = function (
responsePromise,
options
opts
) {
return responsePromise
.then((response) => {
return this.jsonSuccess(response).then(() => {
options?.onSuccess?.(response);
return true;
});
return this.jsonSuccess(response, opts);
})

.catch((err) => {
if (err instanceof Error) {
return handleError(err, this);
}
return this.jsonError(err).then(() => {
options?.onError?.(err);
return true;
});
return this.jsonError(err, opts);
});
};

Expand Down

0 comments on commit d7a1273

Please sign in to comment.