Skip to content

Commit 0dd15fe

Browse files
authored
feat: done mass cleanup and reafctoring (#383)
Refactor public routes to utilize service layer for profile and card retrieval; implement caching and error handling improvements Signed-off-by: Prashantkumar Khatri <prashantkhatri202@gmail.com>
1 parent e2c6f88 commit 0dd15fe

16 files changed

Lines changed: 569 additions & 913 deletions

File tree

apps/backend/src/app.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ export async function buildApp():Promise<FastifyInstance> {
9090
// ─── Auth Decorator ───
9191
app.decorate('authenticate', async function (request: any, reply: any) {
9292
try {
93-
await request.jwtVerify();
93+
// Ensure the verified payload is assigned to `request.user` like the original plugin.
94+
const payload = await request.jwtVerify();
95+
if (payload) request.user = payload;
9496
} catch (error) {
9597
reply.status(401).send({ error: 'Unauthorized' });
9698
}
@@ -100,8 +102,8 @@ export async function buildApp():Promise<FastifyInstance> {
100102
await app.register(authRoutes, { prefix: '/auth' });
101103
await app.register(profileRoutes, { prefix: '/api/profiles' });
102104
await app.register(cardRoutes, { prefix: '/api/cards' });
105+
// Public routes: standardise on `/api/u` (remove duplicate `/api/public`).
103106
await app.register(publicRoutes, { prefix: '/api/u' });
104-
await app.register(publicRoutes, { prefix: '/api/public' });
105107
await app.register(followRoutes, { prefix: '/api/follow' });
106108
await app.register(connectRoutes, { prefix: '/api/connect' });
107109
await app.register(analyticsRoutes, { prefix: '/api/analytics' });
@@ -118,5 +120,20 @@ type HealthResponse = {
118120
app.get('/health', async (): Promise<HealthResponse> => {
119121
return { status: 'ok' };
120122
});
123+
124+
// Centralized error handler: log and return a consistent 500 shape for unhandled errors.
125+
app.setErrorHandler((error, request, reply) => {
126+
app.log.error({ err: error }, 'Unhandled error');
127+
// Also print to console to aid test diagnostics when logger is disabled.
128+
// This helps surface stack traces in CI/test runs.
129+
// eslint-disable-next-line no-console
130+
console.error(error);
131+
// If headers were already sent, fall back to default behaviour.
132+
if (reply.sent) {
133+
return;
134+
}
135+
// Keep response shape consistent across the API.
136+
reply.status(500).send({ error: 'Internal server error' });
137+
});
121138
return app;
122139
}

apps/backend/src/env.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ const envPath = path.resolve(__dirname, '../../../.env');
88
const result = dotenv.config({ path: envPath });
99

1010
if (result.error) {
11-
console.error('❌ Failed to load .env from:', envPath);
12-
console.error(result.error);
11+
// Keep failing fast but avoid leaking via console in production code paths.
12+
// This file runs before the Fastify logger is available; throw so the process exits.
13+
throw result.error;
1314
} else {
14-
console.log('✅ Loaded .env from:', envPath);
15+
// .env loaded successfully
1516
}

apps/backend/src/routes/analytics.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export async function analyticsRoutes(
1212
'/overview',
1313
{
1414
// eslint-disable-next-line @typescript-eslint/unbound-method
15-
preHandler: [app.authenticate],
15+
preHandler: [async (request, reply) => { const server = request.server as any; 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); return } try { await request.jwtVerify() } catch (e) { reply.status(401).send({ error: 'Unauthorized' }) } }],
1616
},
1717
async (
1818
request: FastifyRequest,
@@ -96,7 +96,7 @@ export async function analyticsRoutes(
9696
'/views',
9797
{
9898
// eslint-disable-next-line @typescript-eslint/unbound-method
99-
preHandler: [app.authenticate],
99+
preHandler: [async (request, reply) => { const server = request.server as any; 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); return } try { await request.jwtVerify() } catch (e) { reply.status(401).send({ error: 'Unauthorized' }) } }],
100100
},
101101
async (
102102
request: FastifyRequest<{

0 commit comments

Comments
 (0)