Skip to content

Commit a2a220b

Browse files
authored
fix: improve type safety in follow.ts by removing any usages (#550) (#575)
* fix: remove any usages in follow.ts, reuse Fastify/JWT types (#550) * fix: type jwtVerify payload with AuthenticatedUser * fix: add explicit return type and rename unused catch variable for ESLint
1 parent 076ff4b commit a2a220b

1 file changed

Lines changed: 16 additions & 13 deletions

File tree

apps/backend/src/routes/follow.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
1+
import { getPlatform, getProfileUrl, getWebViewUrl } from '@devcard/shared';
2+
23
import { decrypt } from '../utils/encryption.js';
34
import { getErrorMessage } from '../utils/error.util.js';
4-
import { getPlatform, getProfileUrl, getWebViewUrl } from '@devcard/shared';
55
import { followLogSchema } from '../validations/follow.validation.js';
66

7-
export async function followRoutes(app: FastifyInstance) {
7+
import type { AuthenticatedUser } from '../types/fastify.js';
8+
import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
9+
10+
export async function followRoutes(app: FastifyInstance): Promise<void> {
811
app.addHook('preHandler', async (request, reply) => {
9-
const server = request.server as any;
10-
if (typeof server?.authenticate === 'function') { await server.authenticate(request, reply); return }
11-
if (typeof (app as any).authenticate === 'function') { await (app as any).authenticate(request, reply); return }
12-
try { const payload = await request.jwtVerify(); if (payload) (request as any).user = payload; } catch (e) { reply.status(401).send({ error: 'Unauthorized' }) }
13-
});
12+
const server = request.server;
13+
if (typeof server?.authenticate === 'function') { await server.authenticate(request, reply); return }
14+
if (typeof app.authenticate === 'function') { await app.authenticate(request, reply); return }
15+
try { const payload = await request.jwtVerify<AuthenticatedUser>(); if (payload) {request.user = payload;} } catch (_e) { reply.status(401).send({ error: 'Unauthorized' }) }
16+
});
1417

1518
// ─── Follow via API (Layer 1) ───
1619
// Currently supports: GitHub
@@ -19,7 +22,7 @@ export async function followRoutes(app: FastifyInstance) {
1922
request: FastifyRequest<{ Params: { platform: string; targetUsername: string } }>,
2023
reply: FastifyReply
2124
) => {
22-
const userId = (request.user as any).id;
25+
const userId = request.user.id;
2326
const { platform, targetUsername } = request.params;
2427

2528
// GitHub follow tokens are stored under 'github_follow' to prevent the
@@ -116,7 +119,7 @@ export async function followRoutes(app: FastifyInstance) {
116119
}>,
117120
reply: FastifyReply
118121
) => {
119-
const userId = (request.user as any).id;
122+
const userId = request.user.id;
120123
const { platform, targetUsername } = request.params;
121124

122125
const parsed = followLogSchema.safeParse(request.body);
@@ -137,8 +140,8 @@ export async function followRoutes(app: FastifyInstance) {
137140
},
138141
});
139142
return reply.send({ status: 'success', logId: log.id });
140-
} catch (error: any) {
141-
app.log.error('Failed to log follow:', error);
143+
} catch (error) {
144+
app.log.error(`Failed to log follow: ${getErrorMessage(error)}`);
142145
return reply.status(500).send({ error: 'Failed to log follow event' });
143146
}
144147
});
@@ -148,7 +151,7 @@ export async function followRoutes(app: FastifyInstance) {
148151
request: FastifyRequest<{ Params: { platform: string; targetUsername: string } }>,
149152
reply: FastifyReply
150153
) => {
151-
const userId = (request.user as any).id;
154+
const userId = request.user.id;
152155
const { platform, targetUsername } = request.params;
153156

154157
await app.prisma.followLog.deleteMany({

0 commit comments

Comments
 (0)