Skip to content

Commit

Permalink
feat: add validation with vine
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgevrgs committed Jun 14, 2024
1 parent 37d6581 commit 0c40775
Show file tree
Hide file tree
Showing 17 changed files with 221 additions and 123 deletions.
2 changes: 1 addition & 1 deletion apps/nextjs/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const nextConfig = {
locales: ['en'],
defaultLocale: 'en',
},
transpilePackages: ['@libs/frontend', '@libs/shared', '@libs/backend'],
transpilePackages: ['@libs/*'],
};

export default nextConfig;
3 changes: 2 additions & 1 deletion libs/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"author": "",
"license": "ISC",
"dependencies": {
"@libs/shared": "workspace:*"
"@libs/shared": "workspace:*",
"@vinejs/vine": "2.0.0"
},
"peerDependencies": {
"lodash.omit": "4.5.0",
Expand Down
1 change: 1 addition & 0 deletions libs/backend/src/domain/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './collections.constant';
export * from './regex.constant';
4 changes: 4 additions & 0 deletions libs/backend/src/domain/constants/regex.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const MONGO_ID_REGEX = /^[0-9a-fA-F]{24}$/;

export const FILENAME_REGEX =
/^[a-zA-Z0-9]+(\.png|\.webp|\.jpg|\.jpeg|\.gif|\.bmp)$/;
2 changes: 2 additions & 0 deletions libs/backend/src/domain/schemas/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './request.schema';
export * from './response.schema';
24 changes: 24 additions & 0 deletions libs/backend/src/domain/schemas/request.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import vine from '@vinejs/vine';
import { FILENAME_REGEX, MONGO_ID_REGEX } from '../constants';

const cleanStringSchema = vine.string().trim().escape().toLowerCase();

export const updateVoteBodySchema = vine.object({
vote: vine.enum(['positive', 'negative']),
});

export const updateVoteBodyValidator = vine.compile(updateVoteBodySchema);

export const updateVoteParamsSchema = vine.object({
id: cleanStringSchema.regex(MONGO_ID_REGEX),
});

export const updateVoteParamsValidator = vine.compile(updateVoteParamsSchema);

export const getImageByFilenameParamsSchema = vine.object({
filename: cleanStringSchema.regex(FILENAME_REGEX),
});

export const getImageByFilenameParamsValidator = vine.compile(
getImageByFilenameParamsSchema
);
19 changes: 19 additions & 0 deletions libs/backend/src/domain/schemas/response.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import vine from '@vinejs/vine';
import { MONGO_ID_REGEX } from '../constants';

export const updateVoteResponseSchema = vine.object({
celebrityId: vine.string().regex(MONGO_ID_REGEX),
votes: vine.object({
positive: vine.number(),
negative: vine.number(),
}),
name: vine.string(),
picture: vine.string(),
description: vine.string().optional(),
lastUpdated: vine.date(),
active: vine.boolean(),
});

export const updateVoteResponseValidator = vine.compile(
updateVoteResponseSchema
);

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CelebritiesType } from '@libs/shared';
import { NextApiRequest, NextApiResponse } from 'next';
import { findCelebritiesCollection } from '../../application';

export async function getCelebritiesController(
_req: NextApiRequest,
res: NextApiResponse<CelebritiesType>
) {
const celebrities = await findCelebritiesCollection();

res.status(200).json(celebrities);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { NextApiRequest, NextApiResponse } from 'next';
import sharp from 'sharp';
import { findOneByNameBucket } from '../../application';
import { getImageByFilenameParamsValidator } from '../../domain/schemas';

export async function getCoverByNameController(
req: NextApiRequest,
res: NextApiResponse
) {
// Validate query params
const [params] = await Promise.all([
getImageByFilenameParamsValidator.validate(req.query),
]);

const { filename } = params;

const file = await findOneByNameBucket<NodeJS.ReadableStream>(
filename.replace(/.webp$/, '.png')
);

const output = sharp()
.webp({ quality: 80 })
.resize({
fit: 'cover',
width: 1280,
height: 720,
})
.extend({
background: { r: 255, g: 255, b: 255, alpha: 0.8 },
});

res.setHeader('Content-Type', 'image/webp');
file.pipe(output).pipe(res);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { NextApiRequest, NextApiResponse } from 'next';
import sharp from 'sharp';
import { findOneByNameBucket } from '../../application';
import { getImageByFilenameParamsValidator } from '../../domain/schemas';

export async function getImageByNameController(
req: NextApiRequest,
res: NextApiResponse
) {
// Validate query params
const [params] = await Promise.all([
getImageByFilenameParamsValidator.validate(req.query),
]);

const { filename } = params;

const file = await findOneByNameBucket<NodeJS.ReadableStream>(
filename.replace(/.webp$/, '.png')
);

const output = sharp().webp({ quality: 80 }).resize({
fit: 'contain',
width: 300,
height: 300,
});

res.setHeader('Content-Type', 'image/webp');
file.pipe(output).pipe(res);
}
58 changes: 0 additions & 58 deletions libs/backend/src/infrastructure/controllers/images.controller.ts

This file was deleted.

5 changes: 3 additions & 2 deletions libs/backend/src/infrastructure/controllers/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './celebrities.controller';
export * from './images.controller';
export * from './get-celebrities.controller';
export * from './get-cover-by-name.controller';
export * from './update-vote.controller';
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { CelebrityType } from '@libs/shared';
import { NextApiRequest, NextApiResponse } from 'next';
import { updateCelebrityByIdCollection } from '../../application';
import {
updateVoteBodyValidator,
updateVoteParamsValidator,
} from '../../domain/schemas';

export async function updateVoteController(
req: NextApiRequest,
res: NextApiResponse<CelebrityType>
) {
// Validate body and params
const [body, params] = await Promise.all([
updateVoteBodyValidator.validate(req.body),
updateVoteParamsValidator.validate(req.query),
]);

const { vote } = body;
const { id } = params;

const increment: Record<string, Record<string, number>> = {
positive: { 'votes.positive': 1 },
negative: { 'votes.negative': 1 },
};

const result = await updateCelebrityByIdCollection(id, {
$inc: increment[vote],
});

res.status(200).json(result);
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import type { CelebritiesType } from '@libs/shared';

export async function getCelebritiesService(): Promise<CelebritiesType> {
const response = await fetch(
new URL(
'/api/celebrities',
// import.meta.env.NEXT_FRONTEND_URL
'http://localhost:3000'
)
);
const response = await fetch('/api/celebrities');

if (!response.ok) {
throw new Error(response.statusText);
Expand Down
21 changes: 7 additions & 14 deletions libs/frontend/src/application/services/update-vote.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,13 @@ export async function updateVoteService({
}: UpdateVoteParams): Promise<CelebrityType> {
logger.info('Running updateVoteService', celebrityId, vote);

const response = await fetch(
new URL(
`/api/celebrities/${celebrityId}`,
// import.meta.env.NEXT_FRONTEND_URL
'http://localhost:3000'
),
{
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ vote }),
}
);
const response = await fetch(`/api/celebrities/${celebrityId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ vote }),
});

if (!response.ok) {
throw new Error(response.statusText);
Expand Down
Loading

0 comments on commit 0c40775

Please sign in to comment.