Spaces:
Running
Running
Commit
Β·
e9affa5
1
Parent(s):
4cade40
refactors
Browse files- .vscode/settings.json +1 -0
- src/common/serializers/{user.serializtion.ts β user.serialization.ts} +0 -0
- src/helpers/serialize.ts +21 -2
- src/helpers/validation.helper.ts +7 -5
- src/lib/responses/json-response.ts +90 -20
- src/lib/responses/json-responses-params.d.ts +20 -0
- src/lib/responses/json-responses.d.ts +23 -0
- src/modules/console/common/serializers/{admin.serializtion.ts β admin.serialization.ts} +0 -0
- src/modules/console/modules/admins/controllers/admins.controller.ts +40 -29
- src/modules/console/modules/users/controllers/users.controller.ts +11 -13
- src/modules/users/{auth β modules/auth}/controllers/auth.controller.ts +19 -11
- src/modules/users/{auth β modules/auth}/services/users-auth.service.ts +0 -0
- src/modules/users/{auth β modules/auth}/services/users.service.ts +0 -0
- src/modules/users/{auth β modules/auth}/validation/login.validation.ts +0 -0
- src/modules/users/{exercises β modules/exercises}/controllers/exercises.controller.ts +16 -12
- src/modules/users/{exercises β modules/exercises}/services/exercises.service.ts +0 -0
- src/modules/users/{workouts β modules/workouts}/controllers/workouts.controller.ts +16 -11
- src/modules/users/{workouts β modules/workouts}/services/workouts.service.ts +0 -0
- src/routes.ts +56 -14
.vscode/settings.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"cSpell.words": [
|
|
|
|
| 3 |
"Routable",
|
| 4 |
"tlds"
|
| 5 |
]
|
|
|
|
| 1 |
{
|
| 2 |
"cSpell.words": [
|
| 3 |
+
"IJSON",
|
| 4 |
"Routable",
|
| 5 |
"tlds"
|
| 6 |
]
|
src/common/serializers/{user.serializtion.ts β user.serialization.ts}
RENAMED
|
File without changes
|
src/helpers/serialize.ts
CHANGED
|
@@ -1,14 +1,33 @@
|
|
| 1 |
import { plainToClass } from "class-transformer";
|
|
|
|
| 2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
export const serialize = <T>(
|
| 4 |
-
serializable:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
serializer: new () => T
|
| 6 |
): T | T[] => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
if (Array.isArray(serializable)) {
|
| 8 |
return serializable.map((item) => serialize(item, serializer)) as T[];
|
| 9 |
}
|
| 10 |
|
|
|
|
| 11 |
return plainToClass(serializer, serializable, {
|
| 12 |
excludeExtraneousValues: true,
|
| 13 |
}) as T;
|
| 14 |
-
};
|
|
|
|
| 1 |
import { plainToClass } from "class-transformer";
|
| 2 |
+
import { Document } from "mongoose";
|
| 3 |
|
| 4 |
+
/**
|
| 5 |
+
* Serializes the given object or array of objects into the specified class type.
|
| 6 |
+
*
|
| 7 |
+
* @template T - The class type to serialize the object(s) into.
|
| 8 |
+
* @param serializable - The object or array of objects to be serialized.
|
| 9 |
+
* @param serializer - The class constructor function for the target serialization type.
|
| 10 |
+
* @returns The serialized object(s) of type T or an array of serialized objects of type T.
|
| 11 |
+
*/
|
| 12 |
export const serialize = <T>(
|
| 13 |
+
serializable:
|
| 14 |
+
| Record<string, any>
|
| 15 |
+
| Record<string, any>[]
|
| 16 |
+
| Document
|
| 17 |
+
| Document[],
|
| 18 |
serializer: new () => T
|
| 19 |
): T | T[] => {
|
| 20 |
+
// If the serializable object is a Document, convert it to a JSON object.
|
| 21 |
+
if (serializable.hasOwnProperty("toJSON"))
|
| 22 |
+
serializable = (serializable as Document).toJSON();
|
| 23 |
+
|
| 24 |
+
// If the serializable object is an array, serialize each item in the array.
|
| 25 |
if (Array.isArray(serializable)) {
|
| 26 |
return serializable.map((item) => serialize(item, serializer)) as T[];
|
| 27 |
}
|
| 28 |
|
| 29 |
+
// Serialize the object and return it.
|
| 30 |
return plainToClass(serializer, serializable, {
|
| 31 |
excludeExtraneousValues: true,
|
| 32 |
}) as T;
|
| 33 |
+
};
|
src/helpers/validation.helper.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
import { NextFunction, Request, Response } from "express";
|
| 2 |
import { createValidator } from "express-joi-validation";
|
| 3 |
import Joi from "joi";
|
|
@@ -21,11 +22,12 @@ export const validationErrorHandler = (
|
|
| 21 |
console.log(`err`, err.error);
|
| 22 |
|
| 23 |
const errors = err.error.details.map((detail) => detail.message);
|
| 24 |
-
return
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
|
|
|
| 29 |
} else {
|
| 30 |
// pass on to another error handler
|
| 31 |
next(err);
|
|
|
|
| 1 |
+
import { JsonResponse } from "@lib/responses/json-response";
|
| 2 |
import { NextFunction, Request, Response } from "express";
|
| 3 |
import { createValidator } from "express-joi-validation";
|
| 4 |
import Joi from "joi";
|
|
|
|
| 22 |
console.log(`err`, err.error);
|
| 23 |
|
| 24 |
const errors = err.error.details.map((detail) => detail.message);
|
| 25 |
+
return JsonResponse.validationError(
|
| 26 |
+
{
|
| 27 |
+
errors,
|
| 28 |
+
},
|
| 29 |
+
res
|
| 30 |
+
);
|
| 31 |
} else {
|
| 32 |
// pass on to another error handler
|
| 33 |
next(err);
|
src/lib/responses/json-response.ts
CHANGED
|
@@ -1,24 +1,94 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
-
|
| 19 |
-
this.status = props.status || 200;
|
| 20 |
-
this.message = props.message || "Success";
|
| 21 |
-
this.data = props.data || {};
|
| 22 |
-
this.meta = props.meta;
|
| 23 |
}
|
| 24 |
}
|
|
|
|
| 1 |
+
import { Response } from "express";
|
| 2 |
+
import {
|
| 3 |
+
IJSONSuccessResponse,
|
| 4 |
+
IJSONErrorResponse,
|
| 5 |
+
IJSONValidationErrorResponse,
|
| 6 |
+
} from "./json-responses";
|
| 7 |
+
import {
|
| 8 |
+
IJSONSuccessResponseProps,
|
| 9 |
+
IJSONErrorResponseProps,
|
| 10 |
+
IJSONValidationErrorResponseProps,
|
| 11 |
+
} from "./json-responses-params";
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* Represents a base class for JSON responses.
|
| 15 |
+
*/
|
| 16 |
+
export abstract class JsonResponse {
|
| 17 |
+
private constructor() {}
|
| 18 |
+
|
| 19 |
+
/**
|
| 20 |
+
* Generates a success response object.
|
| 21 |
+
*
|
| 22 |
+
* @param props - The properties for the success response.
|
| 23 |
+
* @param res - Optional Express response object to send the response.
|
| 24 |
+
* @returns The success response object or the Express response object if provided.
|
| 25 |
+
*/
|
| 26 |
+
static success(props: IJSONSuccessResponseProps): IJSONSuccessResponse;
|
| 27 |
+
static success(
|
| 28 |
+
props: IJSONSuccessResponseProps,
|
| 29 |
+
res: Response<IJSONSuccessResponse>
|
| 30 |
+
): Response<IJSONSuccessResponse>;
|
| 31 |
+
static success(
|
| 32 |
+
props: IJSONSuccessResponseProps,
|
| 33 |
+
res?: Response<IJSONSuccessResponse>
|
| 34 |
+
): IJSONSuccessResponse | Response<IJSONSuccessResponse> {
|
| 35 |
+
const data = {
|
| 36 |
+
status: props.status || 200,
|
| 37 |
+
message: props.message || "Success",
|
| 38 |
+
data: props.data,
|
| 39 |
+
meta: props.meta,
|
| 40 |
+
} satisfies IJSONSuccessResponse;
|
| 41 |
+
|
| 42 |
+
return (res && res.status(data.status).json(data)) || data;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
/**
|
| 46 |
+
* Creates a JSON error response.
|
| 47 |
+
* @param props - The properties for the error response.
|
| 48 |
+
* @param res - Optional response object to send the error response.
|
| 49 |
+
* @returns The JSON error response object or the response object if provided.
|
| 50 |
+
*/
|
| 51 |
+
static error(props: IJSONErrorResponseProps): IJSONErrorResponse;
|
| 52 |
+
static error(
|
| 53 |
+
props: IJSONErrorResponseProps,
|
| 54 |
+
res: Response<IJSONErrorResponse>
|
| 55 |
+
): Response<IJSONErrorResponse>;
|
| 56 |
+
static error(
|
| 57 |
+
props: IJSONErrorResponseProps,
|
| 58 |
+
res?: Response<IJSONErrorResponse>
|
| 59 |
+
): IJSONErrorResponse | Response<IJSONErrorResponse> {
|
| 60 |
+
const data = {
|
| 61 |
+
status: props.status || 500,
|
| 62 |
+
message: props.message || "Something Went Wrong",
|
| 63 |
+
error: props.error,
|
| 64 |
+
} satisfies IJSONErrorResponse;
|
| 65 |
+
|
| 66 |
+
return (res && res.status(data.status).json(data)) || data;
|
| 67 |
+
}
|
| 68 |
|
| 69 |
+
/**
|
| 70 |
+
* Represents a validation error response.
|
| 71 |
+
* @param props - The properties of the validation error response.
|
| 72 |
+
* @param res - Optional response object to send the JSON response.
|
| 73 |
+
* @returns The validation error response object or the response object if provided.
|
| 74 |
+
*/
|
| 75 |
+
static validationError(
|
| 76 |
+
props: IJSONValidationErrorResponseProps
|
| 77 |
+
): IJSONValidationErrorResponse;
|
| 78 |
+
static validationError(
|
| 79 |
+
props: IJSONValidationErrorResponseProps,
|
| 80 |
+
res: Response<IJSONValidationErrorResponse>
|
| 81 |
+
): Response<IJSONValidationErrorResponse>;
|
| 82 |
+
static validationError(
|
| 83 |
+
props: IJSONValidationErrorResponseProps,
|
| 84 |
+
res?: Response<IJSONValidationErrorResponse>
|
| 85 |
+
): IJSONValidationErrorResponse | Response<IJSONValidationErrorResponse> {
|
| 86 |
+
const data = {
|
| 87 |
+
status: 422,
|
| 88 |
+
message: "Validation Error",
|
| 89 |
+
errors: props.errors,
|
| 90 |
+
} satisfies IJSONValidationErrorResponse;
|
| 91 |
|
| 92 |
+
return (res && res.status(data.status).json(data)) || data;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
}
|
| 94 |
}
|
src/lib/responses/json-responses-params.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export interface IJSONSuccessResponseProps {
|
| 2 |
+
status?: number;
|
| 3 |
+
message?: string;
|
| 4 |
+
data: Record<string, any> | Record<string, any>[];
|
| 5 |
+
meta?: {
|
| 6 |
+
total: number;
|
| 7 |
+
page: number;
|
| 8 |
+
perPage: number;
|
| 9 |
+
};
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
export interface IJSONErrorResponseProps {
|
| 13 |
+
status?: number;
|
| 14 |
+
message?: string;
|
| 15 |
+
error: string;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
export interface IJSONValidationErrorResponseProps {
|
| 19 |
+
errors: Record<string, any>[];
|
| 20 |
+
}
|
src/lib/responses/json-responses.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
interface IJSONResponse {
|
| 2 |
+
status: number;
|
| 3 |
+
message: string;
|
| 4 |
+
}
|
| 5 |
+
|
| 6 |
+
export interface IJSONSuccessResponse extends IJSONResponse {
|
| 7 |
+
data: Record<string, any> | Record<string, any>[];
|
| 8 |
+
meta?: {
|
| 9 |
+
total: number;
|
| 10 |
+
page: number;
|
| 11 |
+
perPage: number;
|
| 12 |
+
};
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
export interface IJSONErrorResponse extends IJSONResponse {
|
| 16 |
+
error: string;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
export interface IJSONValidationErrorResponse extends IJSONResponse {
|
| 20 |
+
status: 422;
|
| 21 |
+
message: "Validation Error";
|
| 22 |
+
errors: Record<string, any>[];
|
| 23 |
+
}
|
src/modules/console/common/serializers/{admin.serializtion.ts β admin.serialization.ts}
RENAMED
|
File without changes
|
src/modules/console/modules/admins/controllers/admins.controller.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { ControllerMiddleware } from "@lib/decorators/controller-middleware.deco
|
|
| 11 |
import { AdminGuardMiddleware } from "modules/console/common/guards/admins.guard";
|
| 12 |
import { Role } from "@common/enums/role.enum";
|
| 13 |
import { serialize } from "@helpers/serialize";
|
| 14 |
-
import { AdminSerialization } from "modules/console/common/serializers/admin.
|
| 15 |
|
| 16 |
@Prefix("/console/admins")
|
| 17 |
@ControllerMiddleware(AdminGuardMiddleware({ roles: [Role.SUPER_ADMIN] }))
|
|
@@ -39,39 +39,48 @@ export class AdminsController extends BaseController {
|
|
| 39 |
);
|
| 40 |
}
|
| 41 |
|
| 42 |
-
list = async (req: Request, res: Response) => {
|
| 43 |
const paginationQuery = parsePaginationQuery(req.query);
|
| 44 |
const { docs, paginationData } = await this.adminsService.list(
|
| 45 |
{},
|
| 46 |
paginationQuery
|
| 47 |
);
|
| 48 |
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
|
|
|
|
|
|
| 54 |
};
|
| 55 |
|
| 56 |
-
get = async (req: Request, res: Response) => {
|
| 57 |
const data = await this.adminsService.findOneOrFail({
|
| 58 |
_id: req.params.id,
|
| 59 |
});
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
| 64 |
};
|
| 65 |
|
| 66 |
-
create = async (req: Request, res: Response) => {
|
| 67 |
const admin = await this.adminsService.create(req.body);
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
};
|
| 73 |
|
| 74 |
-
update = async (req: Request, res: Response) => {
|
| 75 |
const admin = await this.adminsService.update(
|
| 76 |
{
|
| 77 |
_id: req.params.id,
|
|
@@ -79,22 +88,24 @@ export class AdminsController extends BaseController {
|
|
| 79 |
req.body
|
| 80 |
);
|
| 81 |
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
|
|
|
| 87 |
};
|
| 88 |
|
| 89 |
-
delete = async (req: Request, res: Response) => {
|
| 90 |
const admin = await this.adminsService.delete({
|
| 91 |
_id: req.params.id,
|
| 92 |
});
|
| 93 |
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
|
|
|
| 99 |
};
|
| 100 |
}
|
|
|
|
| 11 |
import { AdminGuardMiddleware } from "modules/console/common/guards/admins.guard";
|
| 12 |
import { Role } from "@common/enums/role.enum";
|
| 13 |
import { serialize } from "@helpers/serialize";
|
| 14 |
+
import { AdminSerialization } from "modules/console/common/serializers/admin.serialization";
|
| 15 |
|
| 16 |
@Prefix("/console/admins")
|
| 17 |
@ControllerMiddleware(AdminGuardMiddleware({ roles: [Role.SUPER_ADMIN] }))
|
|
|
|
| 39 |
);
|
| 40 |
}
|
| 41 |
|
| 42 |
+
list = async (req: Request, res: Response): Promise<Response> => {
|
| 43 |
const paginationQuery = parsePaginationQuery(req.query);
|
| 44 |
const { docs, paginationData } = await this.adminsService.list(
|
| 45 |
{},
|
| 46 |
paginationQuery
|
| 47 |
);
|
| 48 |
|
| 49 |
+
return JsonResponse.success(
|
| 50 |
+
{
|
| 51 |
+
data: serialize(docs, AdminSerialization),
|
| 52 |
+
meta: paginationData,
|
| 53 |
+
},
|
| 54 |
+
res
|
| 55 |
+
);
|
| 56 |
};
|
| 57 |
|
| 58 |
+
get = async (req: Request, res: Response): Promise<Response> => {
|
| 59 |
const data = await this.adminsService.findOneOrFail({
|
| 60 |
_id: req.params.id,
|
| 61 |
});
|
| 62 |
+
|
| 63 |
+
return JsonResponse.success(
|
| 64 |
+
{
|
| 65 |
+
data: serialize(data, AdminSerialization),
|
| 66 |
+
},
|
| 67 |
+
res
|
| 68 |
+
);
|
| 69 |
};
|
| 70 |
|
| 71 |
+
create = async (req: Request, res: Response): Promise<Response> => {
|
| 72 |
const admin = await this.adminsService.create(req.body);
|
| 73 |
+
|
| 74 |
+
return JsonResponse.success(
|
| 75 |
+
{
|
| 76 |
+
status: 201,
|
| 77 |
+
data: serialize(admin, AdminSerialization),
|
| 78 |
+
},
|
| 79 |
+
res
|
| 80 |
+
);
|
| 81 |
};
|
| 82 |
|
| 83 |
+
update = async (req: Request, res: Response): Promise<Response> => {
|
| 84 |
const admin = await this.adminsService.update(
|
| 85 |
{
|
| 86 |
_id: req.params.id,
|
|
|
|
| 88 |
req.body
|
| 89 |
);
|
| 90 |
|
| 91 |
+
return JsonResponse.success(
|
| 92 |
+
{
|
| 93 |
+
data: serialize(admin, AdminSerialization),
|
| 94 |
+
},
|
| 95 |
+
res
|
| 96 |
+
);
|
| 97 |
};
|
| 98 |
|
| 99 |
+
delete = async (req: Request, res: Response): Promise<Response> => {
|
| 100 |
const admin = await this.adminsService.delete({
|
| 101 |
_id: req.params.id,
|
| 102 |
});
|
| 103 |
|
| 104 |
+
return JsonResponse.success(
|
| 105 |
+
{
|
| 106 |
+
data: serialize(admin, AdminSerialization),
|
| 107 |
+
},
|
| 108 |
+
res
|
| 109 |
+
);
|
| 110 |
};
|
| 111 |
}
|
src/modules/console/modules/users/controllers/users.controller.ts
CHANGED
|
@@ -1,31 +1,29 @@
|
|
| 1 |
-
import { userRegisterSchema } from "@common/validations/user-register.validation";
|
| 2 |
import { UsersService } from "../services/users.service";
|
| 3 |
import { JsonResponse } from "@lib/responses/json-response";
|
| 4 |
import { Request, Response } from "express";
|
| 5 |
import { asyncHandler } from "@helpers/async-handler";
|
| 6 |
-
import { bodyValidator } from "@helpers/validation.helper";
|
| 7 |
import { BaseController } from "@lib/controllers/controller.base";
|
| 8 |
import { Prefix } from "@lib/decorators/prefix.decorator";
|
| 9 |
import { serialize } from "@helpers/serialize";
|
| 10 |
-
import { UserSerialization } from "@common/serializers/user.
|
| 11 |
-
|
| 12 |
|
| 13 |
@Prefix("/console/users")
|
| 14 |
export class AdminUsersController extends BaseController {
|
| 15 |
private usersService: UsersService = new UsersService();
|
| 16 |
|
| 17 |
setRoutes() {
|
| 18 |
-
this.router.post(
|
| 19 |
-
"/create",
|
| 20 |
-
asyncHandler(this.create)
|
| 21 |
-
);
|
| 22 |
}
|
| 23 |
|
| 24 |
-
create = async (req: Request, res: Response) => {
|
| 25 |
let user = await this.usersService.create(req.body);
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
};
|
| 31 |
}
|
|
|
|
|
|
|
| 1 |
import { UsersService } from "../services/users.service";
|
| 2 |
import { JsonResponse } from "@lib/responses/json-response";
|
| 3 |
import { Request, Response } from "express";
|
| 4 |
import { asyncHandler } from "@helpers/async-handler";
|
|
|
|
| 5 |
import { BaseController } from "@lib/controllers/controller.base";
|
| 6 |
import { Prefix } from "@lib/decorators/prefix.decorator";
|
| 7 |
import { serialize } from "@helpers/serialize";
|
| 8 |
+
import { UserSerialization } from "@common/serializers/user.serialization";
|
|
|
|
| 9 |
|
| 10 |
@Prefix("/console/users")
|
| 11 |
export class AdminUsersController extends BaseController {
|
| 12 |
private usersService: UsersService = new UsersService();
|
| 13 |
|
| 14 |
setRoutes() {
|
| 15 |
+
this.router.post("/create", asyncHandler(this.create));
|
|
|
|
|
|
|
|
|
|
| 16 |
}
|
| 17 |
|
| 18 |
+
create = async (req: Request, res: Response): Promise<Response> => {
|
| 19 |
let user = await this.usersService.create(req.body);
|
| 20 |
+
|
| 21 |
+
return JsonResponse.success(
|
| 22 |
+
{
|
| 23 |
+
status: 201,
|
| 24 |
+
data: serialize(user, UserSerialization),
|
| 25 |
+
},
|
| 26 |
+
res
|
| 27 |
+
);
|
| 28 |
};
|
| 29 |
}
|
src/modules/users/{auth β modules/auth}/controllers/auth.controller.ts
RENAMED
|
@@ -2,13 +2,16 @@ import { UsersAuthService } from "../services/users.service";
|
|
| 2 |
import { loginValidationSchema } from "../validation/login.validation";
|
| 3 |
import { Request, Response } from "express";
|
| 4 |
import { JsonResponse } from "@lib/responses/json-response";
|
| 5 |
-
import {
|
|
|
|
|
|
|
|
|
|
| 6 |
import { asyncHandler } from "@helpers/async-handler";
|
| 7 |
import { bodyValidator } from "@helpers/validation.helper";
|
| 8 |
import { BaseController } from "@lib/controllers/controller.base";
|
| 9 |
import { Prefix } from "@lib/decorators/prefix.decorator";
|
| 10 |
import { serialize } from "@helpers/serialize";
|
| 11 |
-
import { UserSerialization } from "@common/serializers/user.
|
| 12 |
|
| 13 |
@Prefix("/users/auth")
|
| 14 |
export class UsersAuthController extends BaseController {
|
|
@@ -30,17 +33,22 @@ export class UsersAuthController extends BaseController {
|
|
| 30 |
register = async (req: Request, res: Response) => {
|
| 31 |
const user = await this.authService.register(req.body as IUserRegister);
|
| 32 |
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
|
|
|
|
|
|
| 37 |
};
|
| 38 |
|
| 39 |
-
login = async (req: Request, res: Response) => {
|
| 40 |
const { user, token } = await this.authService.login(req.body);
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
| 45 |
};
|
| 46 |
}
|
|
|
|
| 2 |
import { loginValidationSchema } from "../validation/login.validation";
|
| 3 |
import { Request, Response } from "express";
|
| 4 |
import { JsonResponse } from "@lib/responses/json-response";
|
| 5 |
+
import {
|
| 6 |
+
userRegisterSchema,
|
| 7 |
+
IUserRegister,
|
| 8 |
+
} from "@common/validations/user-register.validation";
|
| 9 |
import { asyncHandler } from "@helpers/async-handler";
|
| 10 |
import { bodyValidator } from "@helpers/validation.helper";
|
| 11 |
import { BaseController } from "@lib/controllers/controller.base";
|
| 12 |
import { Prefix } from "@lib/decorators/prefix.decorator";
|
| 13 |
import { serialize } from "@helpers/serialize";
|
| 14 |
+
import { UserSerialization } from "@common/serializers/user.serialization";
|
| 15 |
|
| 16 |
@Prefix("/users/auth")
|
| 17 |
export class UsersAuthController extends BaseController {
|
|
|
|
| 33 |
register = async (req: Request, res: Response) => {
|
| 34 |
const user = await this.authService.register(req.body as IUserRegister);
|
| 35 |
|
| 36 |
+
return JsonResponse.success(
|
| 37 |
+
{
|
| 38 |
+
data: serialize(user, UserSerialization),
|
| 39 |
+
},
|
| 40 |
+
res
|
| 41 |
+
);
|
| 42 |
};
|
| 43 |
|
| 44 |
+
login = async (req: Request, res: Response): Promise<Response> => {
|
| 45 |
const { user, token } = await this.authService.login(req.body);
|
| 46 |
+
|
| 47 |
+
return JsonResponse.success(
|
| 48 |
+
{
|
| 49 |
+
data: { user: serialize(user, UserSerialization), token },
|
| 50 |
+
},
|
| 51 |
+
res
|
| 52 |
+
);
|
| 53 |
};
|
| 54 |
}
|
src/modules/users/{auth β modules/auth}/services/users-auth.service.ts
RENAMED
|
File without changes
|
src/modules/users/{auth β modules/auth}/services/users.service.ts
RENAMED
|
File without changes
|
src/modules/users/{auth β modules/auth}/validation/login.validation.ts
RENAMED
|
File without changes
|
src/modules/users/{exercises β modules/exercises}/controllers/exercises.controller.ts
RENAMED
|
@@ -11,7 +11,6 @@ import { ExerciseSerialization } from "@common/serializers/exercise.serializtion
|
|
| 11 |
import { ControllerMiddleware } from "@lib/decorators/controller-middleware.decorator";
|
| 12 |
import { UsersGuardMiddleware } from "modules/users/common/guards/users.guard";
|
| 13 |
|
| 14 |
-
|
| 15 |
@Prefix("/users/exercises")
|
| 16 |
@ControllerMiddleware(UsersGuardMiddleware())
|
| 17 |
export class ExerciseController extends BaseController {
|
|
@@ -22,27 +21,32 @@ export class ExerciseController extends BaseController {
|
|
| 22 |
this.router.get("/:id", paramsValidator("id"), asyncHandler(this.get));
|
| 23 |
}
|
| 24 |
|
| 25 |
-
list = async (req: Request, res: Response) => {
|
| 26 |
const paginationQuery = parsePaginationQuery(req.query);
|
| 27 |
const { docs, paginationData } = await this.exercisesService.list(
|
| 28 |
{},
|
| 29 |
paginationQuery
|
| 30 |
);
|
| 31 |
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
|
|
|
|
|
|
| 37 |
};
|
| 38 |
|
| 39 |
-
get = async (req: Request, res: Response) => {
|
| 40 |
const data = await this.exercisesService.findOneOrFail({
|
| 41 |
_id: req.params.id,
|
| 42 |
});
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
| 47 |
};
|
| 48 |
}
|
|
|
|
| 11 |
import { ControllerMiddleware } from "@lib/decorators/controller-middleware.decorator";
|
| 12 |
import { UsersGuardMiddleware } from "modules/users/common/guards/users.guard";
|
| 13 |
|
|
|
|
| 14 |
@Prefix("/users/exercises")
|
| 15 |
@ControllerMiddleware(UsersGuardMiddleware())
|
| 16 |
export class ExerciseController extends BaseController {
|
|
|
|
| 21 |
this.router.get("/:id", paramsValidator("id"), asyncHandler(this.get));
|
| 22 |
}
|
| 23 |
|
| 24 |
+
list = async (req: Request, res: Response): Promise<Response> => {
|
| 25 |
const paginationQuery = parsePaginationQuery(req.query);
|
| 26 |
const { docs, paginationData } = await this.exercisesService.list(
|
| 27 |
{},
|
| 28 |
paginationQuery
|
| 29 |
);
|
| 30 |
|
| 31 |
+
return JsonResponse.success(
|
| 32 |
+
{
|
| 33 |
+
data: serialize(docs, ExerciseSerialization),
|
| 34 |
+
meta: paginationData,
|
| 35 |
+
},
|
| 36 |
+
res
|
| 37 |
+
);
|
| 38 |
};
|
| 39 |
|
| 40 |
+
get = async (req: Request, res: Response): Promise<Response> => {
|
| 41 |
const data = await this.exercisesService.findOneOrFail({
|
| 42 |
_id: req.params.id,
|
| 43 |
});
|
| 44 |
+
|
| 45 |
+
return JsonResponse.success(
|
| 46 |
+
{
|
| 47 |
+
data: serialize(data, ExerciseSerialization),
|
| 48 |
+
},
|
| 49 |
+
res
|
| 50 |
+
);
|
| 51 |
};
|
| 52 |
}
|
src/modules/users/{exercises β modules/exercises}/services/exercises.service.ts
RENAMED
|
File without changes
|
src/modules/users/{workouts β modules/workouts}/controllers/workouts.controller.ts
RENAMED
|
@@ -21,27 +21,32 @@ export class WorkoutController extends BaseController {
|
|
| 21 |
this.router.get("/:id", paramsValidator("id"), asyncHandler(this.get));
|
| 22 |
}
|
| 23 |
|
| 24 |
-
list = async (req: Request, res: Response) => {
|
| 25 |
const paginationQuery = parsePaginationQuery(req.query);
|
| 26 |
const { docs, paginationData } = await this.workoutsService.list(
|
| 27 |
{},
|
| 28 |
paginationQuery
|
| 29 |
);
|
| 30 |
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
| 36 |
};
|
| 37 |
|
| 38 |
-
get = async (req: Request, res: Response) => {
|
| 39 |
const data = await this.workoutsService.findOneOrFail({
|
| 40 |
_id: req.params.id,
|
| 41 |
});
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
| 46 |
};
|
| 47 |
}
|
|
|
|
| 21 |
this.router.get("/:id", paramsValidator("id"), asyncHandler(this.get));
|
| 22 |
}
|
| 23 |
|
| 24 |
+
list = async (req: Request, res: Response): Promise<Response> => {
|
| 25 |
const paginationQuery = parsePaginationQuery(req.query);
|
| 26 |
const { docs, paginationData } = await this.workoutsService.list(
|
| 27 |
{},
|
| 28 |
paginationQuery
|
| 29 |
);
|
| 30 |
|
| 31 |
+
return JsonResponse.success(
|
| 32 |
+
{
|
| 33 |
+
data: serialize(docs, WorkoutSerialization),
|
| 34 |
+
meta: paginationData,
|
| 35 |
+
},
|
| 36 |
+
res
|
| 37 |
+
);
|
| 38 |
};
|
| 39 |
|
| 40 |
+
get = async (req: Request, res: Response): Promise<Response> => {
|
| 41 |
const data = await this.workoutsService.findOneOrFail({
|
| 42 |
_id: req.params.id,
|
| 43 |
});
|
| 44 |
+
|
| 45 |
+
return JsonResponse.success(
|
| 46 |
+
{
|
| 47 |
+
data: serialize(data, WorkoutSerialization),
|
| 48 |
+
},
|
| 49 |
+
res
|
| 50 |
+
);
|
| 51 |
};
|
| 52 |
}
|
src/modules/users/{workouts β modules/workouts}/services/workouts.service.ts
RENAMED
|
File without changes
|
src/routes.ts
CHANGED
|
@@ -4,7 +4,13 @@ import * as glob from "glob";
|
|
| 4 |
import path from "path";
|
| 5 |
import { BaseController } from "./lib/controllers/controller.base";
|
| 6 |
import { validationErrorHandler } from "./helpers/validation.helper";
|
|
|
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
export const setAppRoutes = async (app: Express) => {
|
| 9 |
const mainRouter = Router();
|
| 10 |
|
|
@@ -16,46 +22,77 @@ export const setAppRoutes = async (app: Express) => {
|
|
| 16 |
|
| 17 |
/* custom routes */
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
const setCustomRoutes = (router: Router) => {
|
|
|
|
| 20 |
router.get("/health", (_req: any, res: any) => {
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
});
|
| 25 |
|
|
|
|
| 26 |
router.use(validationErrorHandler);
|
| 27 |
|
|
|
|
| 28 |
router.all("*", (_req: any, res: any) => {
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
});
|
|
|
|
|
|
|
| 33 |
router.use((err, req, res, next) => {
|
| 34 |
try {
|
| 35 |
err.message = JSON.parse(err.message);
|
| 36 |
-
} catch (error) {
|
| 37 |
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
console.error(err.message, err.stack);
|
| 44 |
});
|
| 45 |
-
|
| 46 |
};
|
| 47 |
|
| 48 |
/* importing all controllers */
|
| 49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
const findControllerFiles = (): string[] => {
|
| 51 |
-
const controllersPath = path
|
|
|
|
|
|
|
| 52 |
|
| 53 |
return glob.sync(controllersPath, {}).map((file) => {
|
| 54 |
return path.resolve(file);
|
| 55 |
});
|
| 56 |
};
|
| 57 |
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
const importControllers = async (router: Router) => {
|
| 60 |
const files = findControllerFiles();
|
| 61 |
|
|
@@ -71,6 +108,11 @@ const importControllers = async (router: Router) => {
|
|
| 71 |
);
|
| 72 |
};
|
| 73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
const importController = async (file: string) => {
|
| 75 |
const controllers = Object.values(await import(file));
|
| 76 |
return controllers.find(
|
|
|
|
| 4 |
import path from "path";
|
| 5 |
import { BaseController } from "./lib/controllers/controller.base";
|
| 6 |
import { validationErrorHandler } from "./helpers/validation.helper";
|
| 7 |
+
import { JsonResponse } from "@lib/responses/json-response";
|
| 8 |
|
| 9 |
+
/**
|
| 10 |
+
* Sets the routes for the Express app.
|
| 11 |
+
*
|
| 12 |
+
* @param app - The Express app.
|
| 13 |
+
*/
|
| 14 |
export const setAppRoutes = async (app: Express) => {
|
| 15 |
const mainRouter = Router();
|
| 16 |
|
|
|
|
| 22 |
|
| 23 |
/* custom routes */
|
| 24 |
|
| 25 |
+
/**
|
| 26 |
+
* Sets custom routes for the router.
|
| 27 |
+
*
|
| 28 |
+
* @param router - The router object to set the routes on.
|
| 29 |
+
*/
|
| 30 |
const setCustomRoutes = (router: Router) => {
|
| 31 |
+
// Health check route
|
| 32 |
router.get("/health", (_req: any, res: any) => {
|
| 33 |
+
JsonResponse.success(
|
| 34 |
+
{
|
| 35 |
+
message: "Server is up!",
|
| 36 |
+
data: { success: true },
|
| 37 |
+
},
|
| 38 |
+
res
|
| 39 |
+
);
|
| 40 |
});
|
| 41 |
|
| 42 |
+
// Validation error handler
|
| 43 |
router.use(validationErrorHandler);
|
| 44 |
|
| 45 |
+
// Invalid URL handler
|
| 46 |
router.all("*", (_req: any, res: any) => {
|
| 47 |
+
JsonResponse.error(
|
| 48 |
+
{
|
| 49 |
+
error: "Invalid URL!",
|
| 50 |
+
status: 404,
|
| 51 |
+
},
|
| 52 |
+
res
|
| 53 |
+
);
|
| 54 |
});
|
| 55 |
+
|
| 56 |
+
// Error handler
|
| 57 |
router.use((err, req, res, next) => {
|
| 58 |
try {
|
| 59 |
err.message = JSON.parse(err.message);
|
| 60 |
+
} catch (error) {}
|
| 61 |
|
| 62 |
+
JsonResponse.error(
|
| 63 |
+
{
|
| 64 |
+
error: err.message || "Internal Server Error",
|
| 65 |
+
status: err.status || 500,
|
| 66 |
+
},
|
| 67 |
+
res
|
| 68 |
+
);
|
| 69 |
|
| 70 |
console.error(err.message, err.stack);
|
| 71 |
});
|
|
|
|
| 72 |
};
|
| 73 |
|
| 74 |
/* importing all controllers */
|
| 75 |
|
| 76 |
+
/**
|
| 77 |
+
* Finds all controller files in the project.
|
| 78 |
+
* @returns An array of strings representing the absolute paths of the controller files.
|
| 79 |
+
*/
|
| 80 |
const findControllerFiles = (): string[] => {
|
| 81 |
+
const controllersPath = path
|
| 82 |
+
.relative(process.cwd(), path.join(__dirname, "**/*.controller.{ts,js}"))
|
| 83 |
+
.replace(/\\/g, "/");
|
| 84 |
|
| 85 |
return glob.sync(controllersPath, {}).map((file) => {
|
| 86 |
return path.resolve(file);
|
| 87 |
});
|
| 88 |
};
|
| 89 |
|
| 90 |
+
/**
|
| 91 |
+
* Imports controller classes from files, sets up routes for each controller,
|
| 92 |
+
* and adds them to the provided router.
|
| 93 |
+
*
|
| 94 |
+
* @param router - The router to add the routes to.
|
| 95 |
+
*/
|
| 96 |
const importControllers = async (router: Router) => {
|
| 97 |
const files = findControllerFiles();
|
| 98 |
|
|
|
|
| 108 |
);
|
| 109 |
};
|
| 110 |
|
| 111 |
+
/**
|
| 112 |
+
* Imports a module from a file and returns the first controller that extends BaseController.
|
| 113 |
+
* @param file - The path to the file containing the module.
|
| 114 |
+
* @returns The first controller that extends BaseController.
|
| 115 |
+
*/
|
| 116 |
const importController = async (file: string) => {
|
| 117 |
const controllers = Object.values(await import(file));
|
| 118 |
return controllers.find(
|