44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
import cors from '@fastify/cors';
|
|
import Fastify from 'fastify';
|
|
import { ZodError } from 'zod';
|
|
import { authPlugin } from './auth/plugin.js';
|
|
import { config } from './config.js';
|
|
import { pool } from './db/pool.js';
|
|
import { authRoutes } from './routes/auth.js';
|
|
import { courseRoutes } from './routes/courses.js';
|
|
import { manageCourseRoutes } from './routes/manage-courses.js';
|
|
|
|
export function buildApp() {
|
|
const app = Fastify({ logger: true });
|
|
|
|
app.register(cors, {
|
|
origin: config.FRONTEND_ORIGIN,
|
|
methods: ['GET', 'POST', 'PATCH', 'DELETE'],
|
|
});
|
|
|
|
app.setErrorHandler((error, _request, reply) => {
|
|
if (error instanceof ZodError) {
|
|
return reply.code(400).send({ error: 'Invalid request', details: error.flatten() });
|
|
}
|
|
|
|
app.log.error(error);
|
|
return reply.code(500).send({ error: 'Internal server error' });
|
|
});
|
|
|
|
app.get('/api/v1/health', async () => ({ status: 'ok' }));
|
|
app.get('/api/v1/ready', async (_request, reply) => {
|
|
try {
|
|
await pool.query('select 1');
|
|
return { status: 'ready' };
|
|
} catch {
|
|
return reply.code(503).send({ status: 'unavailable' });
|
|
}
|
|
});
|
|
|
|
app.register(authPlugin);
|
|
app.register(authRoutes, { prefix: '/api/v1/auth' });
|
|
app.register(courseRoutes, { prefix: '/api/v1/courses' });
|
|
app.register(manageCourseRoutes, { prefix: '/api/v1/manage/courses' });
|
|
return app;
|
|
}
|