From 1077cb52beeff34f4c4ff8cfee5479ac6e788b17 Mon Sep 17 00:00:00 2001 From: Satvik Rastogi Date: Wed, 17 Jun 2026 06:42:35 +0530 Subject: [PATCH] fix(backend): remove any usages from profiles.ts to improve type safety --- apps/backend/src/routes/profiles.ts | 69 ++++++++++++++++------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/apps/backend/src/routes/profiles.ts b/apps/backend/src/routes/profiles.ts index 81026c74..388d3e02 100644 --- a/apps/backend/src/routes/profiles.ts +++ b/apps/backend/src/routes/profiles.ts @@ -1,13 +1,10 @@ -import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; -import { getProfileUrl } from '@devcard/shared'; -import { updateProfileSchema, createLinkSchema, reorderLinksSchema } from '../utils/validators.js'; -import { getErrorMessage } from '../utils/error.util.js'; -import * as profileService from '../services/profileService' +import { Prisma } from '@prisma/client'; -// ── Response types ──────────────────────────────────────────────────────────── -// Declared explicitly so the API contract is visible without tracing through -// Prisma's generic return types. Follows the convention in public.ts. +import * as profileService from '../services/profileService'; +import { updateProfileSchema, createLinkSchema, reorderLinksSchema } from '../utils/validators.js'; +import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; +// eslint-disable-next-line @typescript-eslint/no-unused-vars type ProfileUpdateResponse = { id: string; email: string; @@ -21,21 +18,21 @@ type ProfileUpdateResponse = { accentColor: string; }; -export async function profileRoutes(app: FastifyInstance) { +export async function profileRoutes(app: FastifyInstance): Promise { // All profile routes require auth app.addHook('preHandler', async (request, reply) => { - const server = request.server as any; + const server = request.server; if (typeof server?.authenticate === 'function') { await server.authenticate(request, reply); return; } - if (typeof (app as any).authenticate === 'function') { - await (app as any).authenticate(request, reply); + if (typeof app.authenticate === 'function') { + await app.authenticate(request, reply); return; } try { await request.jwtVerify(); - } catch (e) { + } catch (_e) { reply.status(401).send({ error: 'Unauthorized' }); } }); @@ -43,16 +40,18 @@ export async function profileRoutes(app: FastifyInstance) { // ─── Get Own Profile ─── app.get('/me', async (request: FastifyRequest, reply: FastifyReply) => { - const userId = (request.user as any).id; + const userId = request.user.id; const user = await profileService.getOwnProfile(app, userId) - if (!user) return reply.status(404).send({ error: 'User not found' }) + if (!user) { + return reply.status(404).send({ error: 'User not found' }); + } return user }); // ─── Update Profile ─── app.put('/me', async (request: FastifyRequest, reply: FastifyReply) => { - const userId = (request.user as any).id; + const userId = request.user.id; const parsed = updateProfileSchema.safeParse(request.body); if (!parsed.success) { @@ -79,8 +78,10 @@ export async function profileRoutes(app: FastifyInstance) { try { const response = await profileService.updateProfile(app, userId, parsed.data) return response - } catch (err: any) { - if (err?.code === 'P2002') return reply.status(409).send({ error: 'Username already taken' }) + } catch (err: unknown) { + if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === 'P2002') { + return reply.status(409).send({ error: 'Username already taken' }); + } app.log.error({ err }, 'DB error in PUT /profiles/me') return reply.status(500).send({ error: 'Internal server error' }) } @@ -89,7 +90,7 @@ export async function profileRoutes(app: FastifyInstance) { // ─── Add Platform Link ─── app.post('/me/links', async (request: FastifyRequest, reply: FastifyReply) => { - const userId = (request.user as any).id; + const userId = request.user.id; const parsed = createLinkSchema.safeParse(request.body); if (!parsed.success) { @@ -99,7 +100,7 @@ export async function profileRoutes(app: FastifyInstance) { try { const link = await profileService.createPlatformLink(app, userId, parsed.data) return reply.status(201).send(link) - } catch (err: any) { + } catch (err: unknown) { app.log.error({ err }, 'Failed to create platform link') return reply.status(500).send({ error: 'Internal server error' }) } @@ -108,16 +109,20 @@ export async function profileRoutes(app: FastifyInstance) { // ─── Update Platform Link ─── app.put('/me/links/:id', async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => { - const userId = (request.user as any).id; + const userId = request.user.id; const { id } = request.params; const parsedReq = createLinkSchema.safeParse(request.body) - if (!parsedReq.success) return reply.status(400).send({ error: 'Validation failed', details: parsedReq.error.flatten() }) + if (!parsedReq.success) { + return reply.status(400).send({ error: 'Validation failed', details: parsedReq.error.flatten() }); + } try { const updated = await profileService.updatePlatformLink(app, userId, id, parsedReq.data) - if (!updated) return reply.status(404).send({ error: 'Link not found' }) + if (!updated) { + return reply.status(404).send({ error: 'Link not found' }); + } return updated - } catch (err: any) { + } catch (err: unknown) { app.log.error({ err }, 'Failed to update platform link') return reply.status(500).send({ error: 'Internal server error' }) } @@ -126,14 +131,16 @@ export async function profileRoutes(app: FastifyInstance) { // ─── Delete Platform Link ─── app.delete('/me/links/:id', async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => { - const userId = (request.user as any).id; + const userId = request.user.id; const { id } = request.params; try { const deleted = await profileService.deletePlatformLink(app, userId, id) - if (!deleted) return reply.status(404).send({ error: 'Link not found' }) + if (!deleted) { + return reply.status(404).send({ error: 'Link not found' }); + } return reply.status(204).send() - } catch (err: any) { + } catch (err: unknown) { app.log.error({ err }, 'Failed to delete platform link') return reply.status(500).send({ error: 'Internal server error' }) } @@ -142,13 +149,15 @@ export async function profileRoutes(app: FastifyInstance) { // ─── Reorder Links ─── app.put('/me/links/reorder', async (request: FastifyRequest, reply: FastifyReply) => { - const userId = (request.user as any).id; + const userId = request.user.id; const parsedReq = reorderLinksSchema.safeParse(request.body) - if (!parsedReq.success) return reply.status(400).send({ error: 'Validation failed', details: parsedReq.error.flatten() }) + if (!parsedReq.success) { + return reply.status(400).send({ error: 'Validation failed', details: parsedReq.error.flatten() }); + } try { const resp = await profileService.reorderLinks(app, userId, parsedReq.data.links) return resp - } catch (err: any) { + } catch (err: unknown) { app.log.error({ err }, 'Failed to reorder links') return reply.status(500).send({ error: 'Internal server error' }) }