Skip to content

Commit 5fffad9

Browse files
fix(backend): remove any usages from profiles.ts to improve type safety (#589)
1 parent 18809a8 commit 5fffad9

1 file changed

Lines changed: 39 additions & 30 deletions

File tree

apps/backend/src/routes/profiles.ts

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
2-
import { getProfileUrl } from '@devcard/shared';
3-
import { updateProfileSchema, createLinkSchema, reorderLinksSchema } from '../utils/validators.js';
4-
import { getErrorMessage } from '../utils/error.util.js';
5-
import * as profileService from '../services/profileService'
1+
import { Prisma } from '@prisma/client';
62

7-
// ── Response types ────────────────────────────────────────────────────────────
8-
// Declared explicitly so the API contract is visible without tracing through
9-
// Prisma's generic return types. Follows the convention in public.ts.
3+
import * as profileService from '../services/profileService';
4+
import { updateProfileSchema, createLinkSchema, reorderLinksSchema } from '../utils/validators.js';
105

6+
import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
7+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
118
type ProfileUpdateResponse = {
129
id: string;
1310
email: string;
@@ -21,38 +18,40 @@ type ProfileUpdateResponse = {
2118
accentColor: string;
2219
};
2320

24-
export async function profileRoutes(app: FastifyInstance) {
21+
export async function profileRoutes(app: FastifyInstance): Promise<void> {
2522
// All profile routes require auth
2623
app.addHook('preHandler', async (request, reply) => {
27-
const server = request.server as any;
24+
const server = request.server;
2825
if (typeof server?.authenticate === 'function') {
2926
await server.authenticate(request, reply);
3027
return;
3128
}
32-
if (typeof (app as any).authenticate === 'function') {
33-
await (app as any).authenticate(request, reply);
29+
if (typeof app.authenticate === 'function') {
30+
await app.authenticate(request, reply);
3431
return;
3532
}
3633
try {
3734
await request.jwtVerify();
38-
} catch (e) {
35+
} catch (_e) {
3936
reply.status(401).send({ error: 'Unauthorized' });
4037
}
4138
});
4239

4340
// ─── Get Own Profile ───
4441

4542
app.get('/me', async (request: FastifyRequest, reply: FastifyReply) => {
46-
const userId = (request.user as any).id;
43+
const userId = request.user.id;
4744
const user = await profileService.getOwnProfile(app, userId)
48-
if (!user) return reply.status(404).send({ error: 'User not found' })
45+
if (!user) {
46+
return reply.status(404).send({ error: 'User not found' });
47+
}
4948
return user
5049
});
5150

5251
// ─── Update Profile ───
5352

5453
app.put('/me', async (request: FastifyRequest, reply: FastifyReply) => {
55-
const userId = (request.user as any).id;
54+
const userId = request.user.id;
5655
const parsed = updateProfileSchema.safeParse(request.body);
5756

5857
if (!parsed.success) {
@@ -79,8 +78,10 @@ export async function profileRoutes(app: FastifyInstance) {
7978
try {
8079
const response = await profileService.updateProfile(app, userId, parsed.data)
8180
return response
82-
} catch (err: any) {
83-
if (err?.code === 'P2002') return reply.status(409).send({ error: 'Username already taken' })
81+
} catch (err: unknown) {
82+
if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === 'P2002') {
83+
return reply.status(409).send({ error: 'Username already taken' });
84+
}
8485
app.log.error({ err }, 'DB error in PUT /profiles/me')
8586
return reply.status(500).send({ error: 'Internal server error' })
8687
}
@@ -89,7 +90,7 @@ export async function profileRoutes(app: FastifyInstance) {
8990
// ─── Add Platform Link ───
9091

9192
app.post('/me/links', async (request: FastifyRequest, reply: FastifyReply) => {
92-
const userId = (request.user as any).id;
93+
const userId = request.user.id;
9394
const parsed = createLinkSchema.safeParse(request.body);
9495

9596
if (!parsed.success) {
@@ -99,7 +100,7 @@ export async function profileRoutes(app: FastifyInstance) {
99100
try {
100101
const link = await profileService.createPlatformLink(app, userId, parsed.data)
101102
return reply.status(201).send(link)
102-
} catch (err: any) {
103+
} catch (err: unknown) {
103104
app.log.error({ err }, 'Failed to create platform link')
104105
return reply.status(500).send({ error: 'Internal server error' })
105106
}
@@ -108,16 +109,20 @@ export async function profileRoutes(app: FastifyInstance) {
108109
// ─── Update Platform Link ───
109110

110111
app.put('/me/links/:id', async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {
111-
const userId = (request.user as any).id;
112+
const userId = request.user.id;
112113
const { id } = request.params;
113114

114115
const parsedReq = createLinkSchema.safeParse(request.body)
115-
if (!parsedReq.success) return reply.status(400).send({ error: 'Validation failed', details: parsedReq.error.flatten() })
116+
if (!parsedReq.success) {
117+
return reply.status(400).send({ error: 'Validation failed', details: parsedReq.error.flatten() });
118+
}
116119
try {
117120
const updated = await profileService.updatePlatformLink(app, userId, id, parsedReq.data)
118-
if (!updated) return reply.status(404).send({ error: 'Link not found' })
121+
if (!updated) {
122+
return reply.status(404).send({ error: 'Link not found' });
123+
}
119124
return updated
120-
} catch (err: any) {
125+
} catch (err: unknown) {
121126
app.log.error({ err }, 'Failed to update platform link')
122127
return reply.status(500).send({ error: 'Internal server error' })
123128
}
@@ -126,14 +131,16 @@ export async function profileRoutes(app: FastifyInstance) {
126131
// ─── Delete Platform Link ───
127132

128133
app.delete('/me/links/:id', async (request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {
129-
const userId = (request.user as any).id;
134+
const userId = request.user.id;
130135
const { id } = request.params;
131136

132137
try {
133138
const deleted = await profileService.deletePlatformLink(app, userId, id)
134-
if (!deleted) return reply.status(404).send({ error: 'Link not found' })
139+
if (!deleted) {
140+
return reply.status(404).send({ error: 'Link not found' });
141+
}
135142
return reply.status(204).send()
136-
} catch (err: any) {
143+
} catch (err: unknown) {
137144
app.log.error({ err }, 'Failed to delete platform link')
138145
return reply.status(500).send({ error: 'Internal server error' })
139146
}
@@ -142,13 +149,15 @@ export async function profileRoutes(app: FastifyInstance) {
142149
// ─── Reorder Links ───
143150

144151
app.put('/me/links/reorder', async (request: FastifyRequest, reply: FastifyReply) => {
145-
const userId = (request.user as any).id;
152+
const userId = request.user.id;
146153
const parsedReq = reorderLinksSchema.safeParse(request.body)
147-
if (!parsedReq.success) return reply.status(400).send({ error: 'Validation failed', details: parsedReq.error.flatten() })
154+
if (!parsedReq.success) {
155+
return reply.status(400).send({ error: 'Validation failed', details: parsedReq.error.flatten() });
156+
}
148157
try {
149158
const resp = await profileService.reorderLinks(app, userId, parsedReq.data.links)
150159
return resp
151-
} catch (err: any) {
160+
} catch (err: unknown) {
152161
app.log.error({ err }, 'Failed to reorder links')
153162
return reply.status(500).send({ error: 'Internal server error' })
154163
}

0 commit comments

Comments
 (0)