Refactor: further extract controller logic from routers

This commit is contained in:
Aaron William Po
2023-12-04 00:59:13 -05:00
parent da8d5806bc
commit 4b2ce394c1
28 changed files with 325 additions and 308 deletions

View File

@@ -9,8 +9,8 @@ import { z } from 'zod';
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import ImageMetadataValidationSchema from '@/services/schema/ImageSchema/ImageMetadataValidationSchema';
import { uploadMiddlewareMultiple } from '@/config/multer/uploadMiddleware';
import { UploadBeerPostImagesRequest } from '@/controllers/beerImages/types';
import { processBeerImageData } from '@/controllers/beerImages';
import { UploadBeerPostImagesRequest } from '@/controllers/images/beerImages/types';
import { processBeerImageData } from '@/controllers/images/beerImages';
const router = createRouter<
UploadBeerPostImagesRequest,

View File

@@ -6,12 +6,12 @@ import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import { EditBeerPostRequest } from '@/controllers/beerPosts/types';
import { EditBeerPostRequest } from '@/controllers/posts/beerPosts/types';
import {
checkIfBeerPostOwner,
editBeerPost,
deleteBeerPost,
} from '@/controllers/beerPosts';
} from '@/controllers/posts/beerPosts';
import EditBeerPostValidationSchema from '@/services/BeerPost/schema/EditBeerPostValidationSchema';

View File

@@ -1,27 +1,31 @@
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { UserExtendedNextApiRequest } from '@/config/auth/types';
import { createRouter } from 'next-connect';
import { z } from 'zod';
import { NextApiResponse } from 'next';
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import { sendLikeRequest, getLikeCount } from '@/controllers/beerPostLikes';
import {
sendBeerPostLikeRequest,
getBeerPostLikeCount,
} from '@/controllers/likes/beerPostLikes';
import { LikeRequest } from '@/controllers/likes/types';
const router = createRouter<
UserExtendedNextApiRequest,
LikeRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>();
router.post(
getCurrentUser,
validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }),
sendLikeRequest,
sendBeerPostLikeRequest,
);
router.get(
validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }),
getLikeCount,
getBeerPostLikeCount,
);
const handler = router.handler(NextConnectOptions);

View File

@@ -7,7 +7,7 @@ import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect';
import { z } from 'zod';
import { checkIfLiked } from '@/controllers/beerPostLikes';
import { checkIfBeerPostIsLiked } from '@/controllers/likes/beerPostLikes';
const router = createRouter<
UserExtendedNextApiRequest,
@@ -17,7 +17,7 @@ const router = createRouter<
router.get(
getCurrentUser,
validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }),
checkIfLiked,
checkIfBeerPostIsLiked,
);
const handler = router.handler(NextConnectOptions);

View File

@@ -1,7 +1,7 @@
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import { getBeerPostRecommendations } from '@/controllers/beerPosts';
import { GetBeerRecommendationsRequest } from '@/controllers/beerPosts/types';
import { getBeerPostRecommendations } from '@/controllers/posts/beerPosts';
import { GetBeerRecommendationsRequest } from '@/controllers/posts/beerPosts/types';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect';

View File

@@ -7,8 +7,8 @@ import { NextApiResponse } from 'next';
import { z } from 'zod';
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
import { createBeerPost } from '@/controllers/beerPosts';
import { CreateBeerPostRequest } from '@/controllers/beerPosts/types';
import { createBeerPost } from '@/controllers/posts/beerPosts';
import { CreateBeerPostRequest } from '@/controllers/posts/beerPosts/types';
const router = createRouter<
CreateBeerPostRequest,

View File

@@ -1,6 +1,6 @@
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import { getBeerPosts } from '@/controllers/beerPosts';
import { GetAllBeerPostsRequest } from '@/controllers/beerPosts/types';
import { getBeerPosts } from '@/controllers/posts/beerPosts';
import { GetAllBeerPostsRequest } from '@/controllers/posts/beerPosts/types';
import PaginatedQueryResponseSchema from '@/services/schema/PaginatedQueryResponseSchema';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';

View File

@@ -1,7 +1,6 @@
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import DBClient from '@/prisma/DBClient';
import getBeerPostsByBeerStyleId from '@/services/BeerPost/getBeerPostsByBeerStyleId';
import { getAllBeersByBeerStyle } from '@/controllers/posts/beerStyles';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiRequest, NextApiResponse } from 'next';
@@ -12,31 +11,6 @@ interface GetAllBeersByBeerStyleRequest extends NextApiRequest {
query: { page_size: string; page_num: string; id: string };
}
const getAllBeersByBeerStyle = async (
req: GetAllBeersByBeerStyleRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const { page_size, page_num, id } = req.query;
const beers = await getBeerPostsByBeerStyleId({
pageNum: parseInt(page_num, 10),
pageSize: parseInt(page_size, 10),
styleId: id,
});
const count = await DBClient.instance.beerPost.count({ where: { styleId: id } });
res.setHeader('X-Total-Count', count);
res.status(200).json({
message: 'Beers fetched successfully',
statusCode: 200,
payload: beers,
success: true,
});
};
const router = createRouter<
GetAllBeersByBeerStyleRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>

View File

@@ -1,31 +1,12 @@
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import getBeerStyleById from '@/services/BeerStyles/getBeerStyleById';
import { getBeerStyle } from '@/controllers/posts/beerStyles';
import { GetBeerStyleByIdRequest } from '@/controllers/posts/beerStyles/types';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiRequest, NextApiResponse } from 'next';
import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect';
import { z } from 'zod';
interface GetBeerStyleByIdRequest extends NextApiRequest {
query: { id: string };
}
const getBeerStyle = async (
req: GetBeerStyleByIdRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const { id } = req.query;
const beerStyle = await getBeerStyleById(id);
res.status(200).json({
message: 'Beer types retrieved successfully',
statusCode: 200,
payload: beerStyle,
success: true,
});
};
const router = createRouter<
GetBeerStyleByIdRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>

View File

@@ -1,84 +1,32 @@
import { createRouter } from 'next-connect';
import { z } from 'zod';
import { NextApiRequest, NextApiResponse } from 'next';
import { NextApiResponse } from 'next';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import { UserExtendedNextApiRequest } from '@/config/auth/types';
import ServerError from '@/config/util/ServerError';
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import getBeerStyleById from '@/services/BeerStyles/getBeerStyleById';
import findBeerStyleLikeById from '@/services/BeerStyleLike/findBeerStyleLikeById';
import getBeerStyleLikeCount from '@/services/BeerStyleLike/getBeerStyleLikeCount';
import createBeerStyleLike from '@/services/BeerStyleLike/createBeerStyleLike';
import removeBeerStyleLikeById from '@/services/BeerStyleLike/removeBeerStyleLikeById';
const sendLikeRequest = async (
req: UserExtendedNextApiRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const user = req.user!;
const id = req.query.id as string;
const beerStyle = await getBeerStyleById(id);
if (!beerStyle) {
throw new ServerError('Could not find a beer style with that id', 404);
}
const alreadyLiked = await findBeerStyleLikeById({
beerStyleId: beerStyle.id,
likedById: user.id,
});
const jsonResponse = {
success: true as const,
message: '',
statusCode: 200 as const,
};
if (alreadyLiked) {
await removeBeerStyleLikeById({ beerStyleLikeId: alreadyLiked.id });
jsonResponse.message = 'Successfully unliked beer style.';
} else {
await createBeerStyleLike({ beerStyleId: beerStyle.id, user });
jsonResponse.message = 'Successfully liked beer style.';
}
res.status(200).json(jsonResponse);
};
const getLikeCount = async (
req: NextApiRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const id = req.query.id as string;
const likeCount = await getBeerStyleLikeCount({ beerStyleId: id });
res.status(200).json({
success: true,
message: 'Successfully retrieved like count.',
statusCode: 200,
payload: { likeCount },
});
};
import {
getBeerStyleLikeCountRequest,
sendBeerStyleLikeRequest,
} from '@/controllers/likes/beerStyleLikes';
import { LikeRequest } from '@/controllers/likes/types';
const router = createRouter<
UserExtendedNextApiRequest,
LikeRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>();
router.post(
getCurrentUser,
validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }),
sendLikeRequest,
sendBeerStyleLikeRequest,
);
router.get(
validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }),
getLikeCount,
getBeerStyleLikeCountRequest,
);
const handler = router.handler(NextConnectOptions);

View File

@@ -6,37 +6,7 @@ import APIResponseValidationSchema from '@/validation/APIResponseValidationSchem
import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect';
import { z } from 'zod';
import DBClient from '@/prisma/DBClient';
interface FindBeerStyleLikeByIdArgs {
beerStyleId: string;
likedById: string;
}
const findBeerStyleLikeById = async ({
beerStyleId,
likedById,
}: FindBeerStyleLikeByIdArgs) => {
return DBClient.instance.beerStyleLike.findFirst({
where: { beerStyleId, likedById },
});
};
const checkIfLiked = async (
req: UserExtendedNextApiRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const user = req.user!;
const beerStyleId = req.query.id as string;
const alreadyLiked = await findBeerStyleLikeById({ beerStyleId, likedById: user.id });
res.status(200).json({
success: true,
message: alreadyLiked ? 'Beer style is liked.' : 'Beer style is not liked.',
statusCode: 200,
payload: { isLiked: !!alreadyLiked },
});
};
import { checkIfBeerStyleIsLiked } from '@/controllers/likes/beerStyleLikes';
const router = createRouter<
UserExtendedNextApiRequest,
@@ -46,7 +16,7 @@ const router = createRouter<
router.get(
getCurrentUser,
validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }),
checkIfLiked,
checkIfBeerStyleIsLiked,
);
const handler = router.handler(NextConnectOptions);

View File

@@ -1,97 +1,19 @@
import { UserExtendedNextApiRequest } from '@/config/auth/types';
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import ServerError from '@/config/util/ServerError';
import DBClient from '@/prisma/DBClient';
import { createBeerStyle } from '@/controllers/posts/beerStyles';
import { CreateBeerStyleRequest } from '@/controllers/posts/beerStyles/types';
import CreateBeerStyleValidationSchema from '@/services/BeerStyles/schema/CreateBeerStyleValidationSchema';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiRequest, NextApiResponse } from 'next';
import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect';
import { z } from 'zod';
const BeerStyleValidationSchema = z.object({
id: z.string().cuid(),
name: z.string(),
postedBy: z.object({
id: z.string().cuid(),
username: z.string(),
}),
glassware: z.object({
id: z.string().cuid(),
name: z.string(),
description: z.string(),
}),
description: z.string(),
createdAt: z.date(),
updatedAt: z.date().nullable(),
});
const CreateBeerStyleValidationSchema = BeerStyleValidationSchema.omit({
id: true,
postedBy: true,
createdAt: true,
updatedAt: true,
glassware: true,
}).extend({
glasswareId: z.string().cuid(),
});
interface CreateBeerStyleRequest extends UserExtendedNextApiRequest {
body: z.infer<typeof CreateBeerStyleValidationSchema>;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface GetBeerStyleRequest extends NextApiRequest {
query: {
id: string;
};
}
const createBeerStyle = async (
req: CreateBeerStyleRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const user = req.user!;
const { name, description, glasswareId } = req.body;
const glassware = await DBClient.instance.glassware.findUnique({
where: { id: glasswareId },
});
if (!glassware) {
throw new ServerError('Glassware not found', 404);
}
const newBeerStyle = await DBClient.instance.beerStyle.create({
data: {
description,
name,
postedBy: { connect: { id: user.id } },
glassware: { connect: { id: glassware.id } },
},
select: {
id: true,
name: true,
postedBy: { select: { id: true, username: true } },
createdAt: true,
updatedAt: true,
},
});
res.status(200).json({
message: 'Beer posts retrieved successfully',
statusCode: 200,
payload: newBeerStyle,
success: true,
});
};
const router = createRouter<
CreateBeerStyleRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>();
router.get(
router.post(
validateRequest({ bodySchema: CreateBeerStyleValidationSchema }),
getCurrentUser,
createBeerStyle,

View File

@@ -1,39 +1,16 @@
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import DBClient from '@/prisma/DBClient';
import getAllBeerStyles from '@/services/BeerStyles/getAllBeerStyles';
import { getBeerStyles } from '@/controllers/posts/beerStyles';
import { GetAllPostsRequest } from '@/controllers/posts/types';
import PaginatedQueryResponseSchema from '@/services/schema/PaginatedQueryResponseSchema';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiRequest, NextApiResponse } from 'next';
import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect';
import { z } from 'zod';
interface GetBeerStylesRequest extends NextApiRequest {
query: z.infer<typeof PaginatedQueryResponseSchema>;
}
const getBeerStyles = async (
req: GetBeerStylesRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const pageNum = parseInt(req.query.page_num, 10);
const pageSize = parseInt(req.query.page_size, 10);
const beerStyles = await getAllBeerStyles({ pageNum, pageSize });
const beerStyleCount = await DBClient.instance.beerStyle.count();
res.setHeader('X-Total-Count', beerStyleCount);
res.status(200).json({
message: 'Beer types retrieved successfully',
statusCode: 200,
payload: beerStyles,
success: true,
});
};
const router = createRouter<
GetBeerStylesRequest,
GetAllPostsRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>();