Skip to content

Commit

Permalink
refactor: strict mode (#37)
Browse files Browse the repository at this point in the history
* chore: tsconfig

* chore: strict typescript

* chore: some fixes
  • Loading branch information
Michael-Liendo authored Aug 25, 2024
1 parent c7cbfeb commit 837a6f5
Show file tree
Hide file tree
Showing 23 changed files with 71 additions and 49 deletions.
3 changes: 1 addition & 2 deletions client/src/components/datagrids/links/modal-edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,14 @@ export function LinkDialogEdit({
initialValues: {
url: link.url,
shorter_name: link.shorter_name,
id: link.id,
},
validationSchema: toFormikValidationSchema(LinkForUpdateSchema),
validateOnChange: false,
validateOnBlur: false,
onSubmit: async (values) => {
const dto = LinkForUpdateSchema.parse(values);

update(dto);
update(dto, link.id);
setIsOpen(false);
},
});
Expand Down
13 changes: 9 additions & 4 deletions client/src/context/LinksContext.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { useContext } from 'react';

import useAuth from '@/hooks/useAuth';
import type { ILink, ILinkForCreate, ILinkForUpdate } from '@linx/shared';
import type {
ILink,
ILinkForCreate,
ILinkForUpdate,
ILinkForUpdateDTO,
} from '@linx/shared';
import { createContext, useEffect, useState } from 'react';
import Services from '../services';

export interface LinksContextProps {
isLoading: boolean;
links: ILink[] | [];
create: (link: ILinkForCreate) => void;
update: (link: ILinkForUpdate) => void;
update: (link: ILinkForUpdateDTO, id: string) => void;
deleteById: (link_id: string) => void;
}

Expand Down Expand Up @@ -46,8 +51,8 @@ export const LinksProvider = ({ children }: { children?: React.ReactNode }) => {
});
};

const update = async (linkDTO: ILinkForCreate) => {
const updated_link = await Services.link.update(linkDTO);
const update = async (linkDTO: ILinkForUpdateDTO, id: string) => {
const updated_link = await Services.link.update(linkDTO, id);
setLinks((oldLinks) => {
const newList = [...oldLinks];
const index = newList.findIndex((link) => link.id === updated_link.id);
Expand Down
10 changes: 7 additions & 3 deletions client/src/services/Link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { LinkSchema } from '@linx/shared';
import { z } from 'zod';
import fetch from '../utils/fetch';

import type { ILinkForCreate, ILinkForUpdate } from '@linx/shared';
import type {
ILinkForCreate,
ILinkForUpdate,
ILinkForUpdateDTO,
} from '@linx/shared';

export default class Link {
static async getAll() {
Expand Down Expand Up @@ -33,9 +37,9 @@ export default class Link {
}
}

static async update(link: ILinkForUpdate) {
static async update(link: ILinkForUpdateDTO, id: string) {
try {
const request = await fetch(`/links/edit/${link.id}`, {
const request = await fetch(`/links/edit/${id}`, {
method: 'PUT',
body: JSON.stringify(link),
});
Expand Down
4 changes: 2 additions & 2 deletions server/src/controllers/Auth/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { BadRequestError } from '../../utils/errorHandler.js';

import type { IUserForLogin } from '@linx/shared';
import type { FastifyRequest } from 'fastify';
import type { Reply } from '../../types/index.js';
import type { Reply, Request } from '../../types/index.js';

export default async function login(request: FastifyRequest, reply: Reply) {
export default async function login(request: Request, reply: Reply) {
const { email, password } = request.body as IUserForLogin;

if (!email || !password) {
Expand Down
4 changes: 2 additions & 2 deletions server/src/controllers/Link/create.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import Services from '../../services/index.js';
import { BadRequestError } from '../../utils/errorHandler.js';

import type { ILinkForCreate } from '@linx/shared';
import type { ILinkForCreate, IUser } from '@linx/shared';
import type { Reply, Request } from '../../types/index.js';

export default async function create(request: Request, reply: Reply) {
const { shorter_name, url } = request.body as ILinkForCreate;
const user = request.user;
const user = request.user as IUser;

if (!shorter_name || !url) {
throw new BadRequestError('Please provide all required fields');
Expand Down
4 changes: 2 additions & 2 deletions server/src/controllers/Link/delete.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import Services from '../../services/index.js';
import { BadRequestError } from '../../utils/errorHandler.js';

import type { ILinkForDelete } from '@linx/shared';
import type { ILinkForDelete, IUser } from '@linx/shared';
import type { Reply, Request } from '../../types/index.js';

export default async function deleteByID(request: Request, reply: Reply) {
const { id } = request.params as ILinkForDelete;
const user = request.user;
const user = request.user as IUser;

const link = await Services.link.deleteByIdUser(id, user.id);

Expand Down
4 changes: 2 additions & 2 deletions server/src/controllers/Link/getAll.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Services from '../../services/index.js';
import { BadRequestError } from '../../utils/errorHandler.js';

import type { ILinkForCreate } from '@linx/shared';
import type { ILinkForCreate, IUser } from '@linx/shared';
import type { Reply, Request } from '../../types/index.js';

export default async function getAll(request: Request, reply: Reply) {
const user = request.user;
const user = request.user as IUser;

const links = await Services.link.getAllByUser(user.id);

Expand Down
6 changes: 3 additions & 3 deletions server/src/controllers/Link/update.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import Services from '../../services/index.js';

import type { ILinkForUpdate } from '@linx/shared';
import type { ILinkForUpdate, ILinkForUpdateDTO, IUser } from '@linx/shared';
import type { Reply, Request } from '../../types/index.js';

export default async function update(request: Request, reply: Reply) {
const data = request.body as ILinkForUpdate;
const data = request.body as ILinkForUpdateDTO;
const { id } = request.params as { id: string };
const user = request.user;
const user = request.user as IUser;

const link = await Services.link.update(user.id, { id, ...data });
return reply.code(200).send({
Expand Down
3 changes: 2 additions & 1 deletion server/src/controllers/User/me.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { IUser } from '@linx/shared';
import type { Reply, Request } from '../../types/index.js';

export default async function me(request: Request, reply: Reply) {
const { password, ...user } = request.user;
const { password, ...user } = request.user as IUser;
return reply.code(200).send({ success: true, message: 'Ok', data: { user } });
}
2 changes: 1 addition & 1 deletion server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const fastify = Fastify();

// Cors
fastify.register(cors, {
origin: process.env.CORS_ORIGIN.split(',') || '*',
origin: process.env?.CORS_ORIGIN?.split(',') || '*',
});

// Declare a route
Expand Down
13 changes: 8 additions & 5 deletions server/src/middlewares/checkJwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import Services from '../services/index.js';
import { UnauthorizedError } from '../utils/errorHandler.js';
import { Jwt } from '../utils/jwt.js';

import type { DoneFuncWithErrOrRes, FastifyInstance } from 'fastify';
import type { FastifyInstance, FastifyRequest } from 'fastify';
import type { Request } from '../types/index.js';

function getUser(fastify: FastifyInstance, _, done: DoneFuncWithErrOrRes) {
fastify.decorateRequest('user', null);

function getUser(fastify: FastifyInstance, _: unknown, done: () => void) {
fastify.decorateRequest('user', undefined);
fastify.addHook('preHandler', checkJwt);
done();
}
Expand All @@ -26,9 +25,13 @@ async function checkJwt(request: Request) {
const payload = Jwt.verifyToken(`${jwt}`);
const user = await Services.user.getByID(payload.id);

if (!user) {
throw new UnauthorizedError('Access denied');
}

request.user = user;
} catch (error) {
throw new UnauthorizedError(error);
throw new UnauthorizedError(error as string);
}
}

Expand Down
13 changes: 9 additions & 4 deletions server/src/repository/Link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,22 @@ export class Link {
return link;
}

static async getByShorterName(shorter_name: string): Promise<ILink | null> {
const link: ILink | null = await database<ILink>('links')
static async getByShorterName(
shorter_name: string,
): Promise<ILink | undefined> {
const link = await database<ILink>('links')
.select('*')
.where({ shorter_name: shorter_name })
.first();

return link;
}

static async getById(id: string): Promise<ILink> {
const [link] = await database<ILink>('links').select('*').where({ id: id });
static async getById(id: string): Promise<ILink | undefined> {
const link = await database<ILink>('links')
.select('*')
.where({ id: id })
.first();
return link;
}

Expand Down
6 changes: 3 additions & 3 deletions server/src/repository/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ export class User {
* @param id string
* @returns string IUser
*/
static async getUserByEmail(email: string): Promise<IUser | null> {
const user = await database('users').where({ email }).first();
static async getUserByEmail(email: string): Promise<IUser | undefined> {
const user = await database<IUser>('users').where({ email }).first();
return user;
}

Expand All @@ -17,7 +17,7 @@ export class User {
* @param id string
* @returns string IUser
*/
static async getUserByID(id: string): Promise<IUser | null> {
static async getUserByID(id: string): Promise<IUser | undefined> {
const user = await database('users').where({ id }).first();

return user;
Expand Down
2 changes: 1 addition & 1 deletion server/src/routes/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import requestValidation from '../../utils/requestValidation.js';
export default function auth(
fastify: FastifyInstance,
_: RegisterOptions,
done: DoneFuncWithErrOrRes,
done: () => void,
) {
fastify.route({
method: 'POST',
Expand Down
2 changes: 1 addition & 1 deletion server/src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { ErrorWithDetails } from '../utils/errorHandler.js';
export default function routes(
fastify: FastifyInstance,
_: RegisterOptions,
done: DoneFuncWithErrOrRes,
done: () => void,
) {
fastify.setErrorHandler((error: ErrorWithDetails, _, reply) => {
if (error.statusCode >= 500) {
Expand Down
2 changes: 1 addition & 1 deletion server/src/routes/link/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import update from '../../controllers/Link/update.js';
export default function link(
fastify: FastifyInstance,
_: RegisterOptions,
done: DoneFuncWithErrOrRes,
done: () => void,
) {
fastify.register(checkJwt);

Expand Down
3 changes: 1 addition & 2 deletions server/src/routes/user/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import me from '../../controllers/User/me.js';
import checkJwt from '../../middlewares/checkJwt.js';

import type { IReply } from '@linx/shared';
import type {
DoneFuncWithErrOrRes,
FastifyInstance,
Expand All @@ -11,7 +10,7 @@ import type {
export default function user(
fastify: FastifyInstance,
_: RegisterOptions,
done: DoneFuncWithErrOrRes,
done: () => void,
) {
fastify.register(checkJwt);

Expand Down
8 changes: 4 additions & 4 deletions server/src/services/Auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ import Repository from '../repository/index.js';
import { BadRequestError, UnauthorizedError } from '../utils/errorHandler.js';
import { comparePassword, hashPassword } from '../utils/password.js';

import type { IUserForLogin, IUserForRegister } from '@linx/shared';
import type { IUser, IUserForLogin, IUserForRegister } from '@linx/shared';
import { Jwt } from '../utils/jwt.js';

export default class Auth {
static async login(data: IUserForLogin) {
const { password, ...user } = await Repository.user.getUserByEmail(
data.email,
);
const user = await Repository.user.getUserByEmail(data.email);

if (!user) {
throw new UnauthorizedError('UnauthorizedError');
}

const { password } = user as Required<IUser>;

const isCorrectPassword = await comparePassword(data.password, password);

if (!isCorrectPassword) {
Expand Down
4 changes: 2 additions & 2 deletions server/src/services/Link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default class Link {
static async update(user_id: string, link_dto: ILinkForUpdate) {
try {
const check = await Repository.link.getById(link_dto.id);
if (check.user_id !== user_id)
if (check?.user_id !== user_id)
throw new UnauthorizedError('You no are the owner of this link');
const check_name = await Repository.link.getByShorterName(
link_dto.shorter_name,
Expand All @@ -58,7 +58,7 @@ export default class Link {
user_id: string,
): Promise<string> {
const check = await Repository.link.getById(link_id);
if (check.user_id !== user_id)
if (check?.user_id !== user_id)
throw new UnauthorizedError('You no are the owner of this link');

const deleted_link_id = await Repository.link.deleteById(link_id);
Expand Down
2 changes: 1 addition & 1 deletion server/src/services/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { IUser } from '@linx/shared';
import Repository from '../repository/index.js';

export default class User {
static async getByID(userID: string): Promise<IUser | null> {
static async getByID(userID: string): Promise<IUser | undefined> {
const user = await Repository.user.getUserByID(userID);

return user;
Expand Down
4 changes: 3 additions & 1 deletion server/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"target": "ES2020",
"declaration": true,
"module": "NodeNext",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist"
}
},
"exclude": ["node_modules", "dist"]
}
7 changes: 6 additions & 1 deletion shared/src/interfaces/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ export interface ILinkForCreate {
}

export interface ILinkForUpdate {
id?: string;
id: string;
url: string;
shorter_name: string;
}

export interface ILinkForUpdateDTO {
url: string;
shorter_name: string;
}
Expand Down
1 change: 0 additions & 1 deletion shared/src/schema/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export const LinkForCreateSchema = z.object({
});

export const LinkForUpdateSchema = z.object({
id: z.string().optional(),
url: z.string().url(),
shorter_name: z.string().max(20),
});
Expand Down

0 comments on commit 837a6f5

Please sign in to comment.