Skip to content

Commit

Permalink
refactor(users): improve api readability using safeApiCall reusable f…
Browse files Browse the repository at this point in the history
…unction
  • Loading branch information
WillACosta committed Oct 1, 2024
1 parent 02895a0 commit 21f84c9
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ app.use(express.json())

app.use('/', AuthRoutes)
app.use('/status', StatusRoutes)
app.use('/user', UserRoutes)
app.use('/users', UserRoutes)
app.use('/gen-ai', GenAIRoutes)

app.listen(port, () => {
Expand Down
1 change: 1 addition & 0 deletions src/common/functions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './safe-api-call.function'
21 changes: 21 additions & 0 deletions src/common/functions/safe-api-call.function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { AppResponse } from '../types'

type ApiHandler<T> = () => Promise<T>

export async function safeApiCall<T>(
handler: ApiHandler<T>,
res: AppResponse<T>,
): Promise<AppResponse<T>> {
try {
const data = await handler()
return res.status(200).json({
success: true,
data,
})
} catch (err: any) {
return res.status(500).json({
success: false,
error: err,
})
}
}
11 changes: 4 additions & 7 deletions src/common/middlewares/is-authenticated.middleware.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { NextFunction, Request, Response } from 'express'
import { NextFunction, Response } from 'express'
import jwt from 'jsonwebtoken'

export interface AuthRequest extends Request {
user?: object
token?: string
}
import { AppRequest } from '../types'

export function isAuthenticated(
req: AuthRequest,
req: AppRequest,
res: Response,
next: NextFunction,
) {
Expand All @@ -26,7 +23,7 @@ export function isAuthenticated(
return res.status(401).json({
success: false,
error: {
message: 'Invalid auth mechanism.',
message: 'Invalid auth mechanism. This API supports only Bearer token.',
},
})
}
Expand Down
3 changes: 2 additions & 1 deletion src/common/types/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './usecase.type'
export * from './network.types'
export * from './usecase.types'
20 changes: 20 additions & 0 deletions src/common/types/network.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { User } from '@/modules/users/core'
import { Request, Response } from 'express'

export interface AppRequest<
P extends { [key: string]: string } = {
[key: string]: string
},
T = any,
R = any,
S = any,
> extends Request<P, T, R, S> {
user?: User
token?: string
}

export type AppResponse<T = any> = Response<{
success: boolean
data?: T
error?: { message: string; code?: string }
}>
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export interface UseCase<R, P> {
invoke(params: P): Promise<R>
}
}
36 changes: 28 additions & 8 deletions src/modules/users/adapters/dataproviders/user.dataprovider.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,71 @@
import { prismaClient } from '@/di'
import { Prisma } from '@prisma/client'
import { UserParams } from '../../core'

export type PrismaUser = Prisma.PromiseReturnType<
typeof UserDataProvider.prototype.getUserById
>

export class UserDataProvider {
async insert({ name, email, password }: UserParams) {
private _selectUserProperties = {
id: true,
name: true,
email: true,
createdAt: true,
}

insert = async ({ name, email, password }: UserParams) => {
return await prismaClient.users.create({
data: {
name,
email,
password,
},
select: this._selectUserProperties,
})
}

async update({ id, name, email, password }: UserParams) {
update = async (
id: string,
{ name, email }: { name: string; email: string },
) => {
return await prismaClient.users.update({
where: {
id,
},
data: {
name,
email,
password,
},
select: this._selectUserProperties,
})
}

async delete(id: string) {
delete = async (id: string) => {
return await prismaClient.users.delete({
where: {
id,
},
select: this._selectUserProperties,
})
}

async getAllUsers() {
return await prismaClient.users.findMany()
getAllUsers = async () => {
return await prismaClient.users.findMany({
select: this._selectUserProperties,
})
}

async getUserById(id: string) {
getUserById = async (id: string) => {
return await prismaClient.users.findUnique({
where: {
id,
},
select: this._selectUserProperties,
})
}

async findUserByEmail(email: string) {
findUserByEmail = async (email: string) => {
return await prismaClient.users.findUnique({
where: {
email,
Expand Down
45 changes: 39 additions & 6 deletions src/modules/users/application/controllers/users.controller.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,45 @@
import { Request, Response } from 'express'
import { AppRequest, AppResponse } from '@/common/types'

import { UserDataProvider } from '../../adapters/dataproviders/user.dataprovider'
import {
PrismaUser,
UserDataProvider,
} from '../../adapters/dataproviders/user.dataprovider'

import { safeApiCall } from '@/common/functions'

export class UsersController {
constructor(private _userProvider: UserDataProvider) {}

async getUser(req: Request, res: Response) {}
async getAllUsers() {}
async updateUser() {}
async deleteUser() {}
getUser = async (req: AppRequest, res: AppResponse<PrismaUser>) => {
return await safeApiCall(
() => this._userProvider.getUserById(req.user?.id!),
res,
)
}

getAllUsers = async (_req: AppRequest, res: AppResponse<PrismaUser[]>) => {
return await safeApiCall(() => this._userProvider.getAllUsers(), res)
}

updateUser = async (
req: AppRequest<{ id: string }>,
res: AppResponse<PrismaUser>,
) => {
const { id } = req.params
const { name, email } = req.body

return await safeApiCall(
() =>
this._userProvider.update(id, {
name,
email,
}),
res,
)
}

deleteUser = async (req: AppRequest, res: AppResponse) => {
const { id } = req.params
return await safeApiCall(() => this._userProvider.delete(id), res)
}
}
2 changes: 1 addition & 1 deletion src/modules/users/core/entities/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export type User = {
id?: string
id: string
email: string
createdAt: Date
password: string
Expand Down

0 comments on commit 21f84c9

Please sign in to comment.