style: run prettier on entire codebase
This commit is contained in:
213
src/server.ts
213
src/server.ts
@@ -1,40 +1,40 @@
|
||||
import Fastify from 'fastify';
|
||||
import cors from '@fastify/cors';
|
||||
import cookie from '@fastify/cookie';
|
||||
import rateLimit from '@fastify/rate-limit';
|
||||
import path from 'path';
|
||||
import { config } from './config/env';
|
||||
import { securityHeaders } from './middleware/security';
|
||||
import Fastify from "fastify";
|
||||
import cors from "@fastify/cors";
|
||||
import cookie from "@fastify/cookie";
|
||||
import rateLimit from "@fastify/rate-limit";
|
||||
import path from "path";
|
||||
import { config } from "./config/env";
|
||||
import { securityHeaders } from "./middleware/security";
|
||||
|
||||
// Route imports
|
||||
import authRoutes from './routes/admin/auth';
|
||||
import usersRoutes from './routes/admin/users';
|
||||
import rolesRoutes from './routes/admin/roles';
|
||||
import attendanceRoutes from './routes/admin/attendance';
|
||||
import customersRoutes from './routes/admin/customers';
|
||||
import invoicesRoutes from './routes/admin/invoices';
|
||||
import quotationsRoutes from './routes/admin/quotations';
|
||||
import ordersRoutes from './routes/admin/orders';
|
||||
import projectsRoutes from './routes/admin/projects';
|
||||
import tripsRoutes from './routes/admin/trips';
|
||||
import vehiclesRoutes from './routes/admin/vehicles';
|
||||
import leaveRequestsRoutes from './routes/admin/leave-requests';
|
||||
import bankAccountsRoutes from './routes/admin/bank-accounts';
|
||||
import companySettingsRoutes from './routes/admin/company-settings';
|
||||
import receivedInvoicesRoutes from './routes/admin/received-invoices';
|
||||
import dashboardRoutes from './routes/admin/dashboard';
|
||||
import auditLogRoutes from './routes/admin/audit-log';
|
||||
import profileRoutes from './routes/admin/profile';
|
||||
import sessionsRoutes from './routes/admin/sessions';
|
||||
import totpRoutes from './routes/admin/totp';
|
||||
import scopeTemplatesRoutes from './routes/admin/scope-templates';
|
||||
import invoicesPdfRoutes from './routes/admin/invoices-pdf';
|
||||
import offersPdfRoutes from './routes/admin/offers-pdf';
|
||||
import projectFilesRoutes from './routes/admin/project-files';
|
||||
import authRoutes from "./routes/admin/auth";
|
||||
import usersRoutes from "./routes/admin/users";
|
||||
import rolesRoutes from "./routes/admin/roles";
|
||||
import attendanceRoutes from "./routes/admin/attendance";
|
||||
import customersRoutes from "./routes/admin/customers";
|
||||
import invoicesRoutes from "./routes/admin/invoices";
|
||||
import quotationsRoutes from "./routes/admin/quotations";
|
||||
import ordersRoutes from "./routes/admin/orders";
|
||||
import projectsRoutes from "./routes/admin/projects";
|
||||
import tripsRoutes from "./routes/admin/trips";
|
||||
import vehiclesRoutes from "./routes/admin/vehicles";
|
||||
import leaveRequestsRoutes from "./routes/admin/leave-requests";
|
||||
import bankAccountsRoutes from "./routes/admin/bank-accounts";
|
||||
import companySettingsRoutes from "./routes/admin/company-settings";
|
||||
import receivedInvoicesRoutes from "./routes/admin/received-invoices";
|
||||
import dashboardRoutes from "./routes/admin/dashboard";
|
||||
import auditLogRoutes from "./routes/admin/audit-log";
|
||||
import profileRoutes from "./routes/admin/profile";
|
||||
import sessionsRoutes from "./routes/admin/sessions";
|
||||
import totpRoutes from "./routes/admin/totp";
|
||||
import scopeTemplatesRoutes from "./routes/admin/scope-templates";
|
||||
import invoicesPdfRoutes from "./routes/admin/invoices-pdf";
|
||||
import offersPdfRoutes from "./routes/admin/offers-pdf";
|
||||
import projectFilesRoutes from "./routes/admin/project-files";
|
||||
|
||||
const app = Fastify({
|
||||
logger: {
|
||||
level: config.isProduction ? 'warn' : 'info',
|
||||
level: config.isProduction ? "warn" : "info",
|
||||
},
|
||||
trustProxy: true,
|
||||
bodyLimit: 1048576,
|
||||
@@ -43,76 +43,105 @@ const app = Fastify({
|
||||
async function start() {
|
||||
// --- Plugins ---
|
||||
await app.register(cors, {
|
||||
origin: config.appEnv === 'local'
|
||||
? [/^http:\/\/127\.0\.0\.1:\d+$/, /^http:\/\/localhost:\d+$/, /^http:\/\/192\.168\.\d+\.\d+:\d+$/]
|
||||
: config.cors.origins,
|
||||
origin:
|
||||
config.appEnv === "local"
|
||||
? [
|
||||
/^http:\/\/127\.0\.0\.1:\d+$/,
|
||||
/^http:\/\/localhost:\d+$/,
|
||||
/^http:\/\/192\.168\.\d+\.\d+:\d+$/,
|
||||
]
|
||||
: config.cors.origins,
|
||||
credentials: true,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
|
||||
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
||||
allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
|
||||
});
|
||||
|
||||
await app.register(cookie);
|
||||
|
||||
await app.register(rateLimit, {
|
||||
max: 100,
|
||||
timeWindow: '1 minute',
|
||||
timeWindow: "1 minute",
|
||||
});
|
||||
|
||||
// --- Security headers ---
|
||||
app.addHook('onRequest', securityHeaders);
|
||||
app.addHook("onRequest", securityHeaders);
|
||||
|
||||
// --- Global error handler — consistent { success, error } format ---
|
||||
app.setErrorHandler((err: Error & { statusCode?: number }, request, reply) => {
|
||||
const statusCode = err.statusCode ?? 500;
|
||||
if (statusCode >= 500) {
|
||||
request.log.error(err);
|
||||
}
|
||||
reply.status(statusCode).send({
|
||||
success: false,
|
||||
error: statusCode >= 500 ? 'Interní chyba serveru' : (err.message || 'Chyba požadavku'),
|
||||
});
|
||||
});
|
||||
app.setErrorHandler(
|
||||
(err: Error & { statusCode?: number }, request, reply) => {
|
||||
const statusCode = err.statusCode ?? 500;
|
||||
if (statusCode >= 500) {
|
||||
request.log.error(err);
|
||||
}
|
||||
reply.status(statusCode).send({
|
||||
success: false,
|
||||
error:
|
||||
statusCode >= 500
|
||||
? "Interní chyba serveru"
|
||||
: err.message || "Chyba požadavku",
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// --- API Routes ---
|
||||
await app.register(authRoutes, { prefix: '/api/admin' });
|
||||
await app.register(usersRoutes, { prefix: '/api/admin/users' });
|
||||
await app.register(rolesRoutes, { prefix: '/api/admin/roles' });
|
||||
await app.register(attendanceRoutes, { prefix: '/api/admin/attendance' });
|
||||
await app.register(customersRoutes, { prefix: '/api/admin/customers' });
|
||||
await app.register(invoicesRoutes, { prefix: '/api/admin/invoices' });
|
||||
await app.register(quotationsRoutes, { prefix: '/api/admin/offers' });
|
||||
await app.register(ordersRoutes, { prefix: '/api/admin/orders' });
|
||||
await app.register(projectsRoutes, { prefix: '/api/admin/projects' });
|
||||
await app.register(tripsRoutes, { prefix: '/api/admin/trips' });
|
||||
await app.register(vehiclesRoutes, { prefix: '/api/admin/vehicles' });
|
||||
await app.register(leaveRequestsRoutes, { prefix: '/api/admin/leave-requests' });
|
||||
await app.register(bankAccountsRoutes, { prefix: '/api/admin/bank-accounts' });
|
||||
await app.register(companySettingsRoutes, { prefix: '/api/admin/company-settings' });
|
||||
await app.register(receivedInvoicesRoutes, { prefix: '/api/admin/received-invoices' });
|
||||
await app.register(dashboardRoutes, { prefix: '/api/admin/dashboard' });
|
||||
await app.register(auditLogRoutes, { prefix: '/api/admin/audit-log' });
|
||||
await app.register(profileRoutes, { prefix: '/api/admin/profile' });
|
||||
await app.register(sessionsRoutes, { prefix: '/api/admin/sessions' });
|
||||
await app.register(totpRoutes, { prefix: '/api/admin/totp' });
|
||||
await app.register(scopeTemplatesRoutes, { prefix: '/api/admin/offers-templates' });
|
||||
await app.register(invoicesPdfRoutes, { prefix: '/api/admin/invoices-pdf' });
|
||||
await app.register(offersPdfRoutes, { prefix: '/api/admin/offers-pdf' });
|
||||
await app.register(projectFilesRoutes, { prefix: '/api/admin/project-files' });
|
||||
await app.register(authRoutes, { prefix: "/api/admin" });
|
||||
await app.register(usersRoutes, { prefix: "/api/admin/users" });
|
||||
await app.register(rolesRoutes, { prefix: "/api/admin/roles" });
|
||||
await app.register(attendanceRoutes, { prefix: "/api/admin/attendance" });
|
||||
await app.register(customersRoutes, { prefix: "/api/admin/customers" });
|
||||
await app.register(invoicesRoutes, { prefix: "/api/admin/invoices" });
|
||||
await app.register(quotationsRoutes, { prefix: "/api/admin/offers" });
|
||||
await app.register(ordersRoutes, { prefix: "/api/admin/orders" });
|
||||
await app.register(projectsRoutes, { prefix: "/api/admin/projects" });
|
||||
await app.register(tripsRoutes, { prefix: "/api/admin/trips" });
|
||||
await app.register(vehiclesRoutes, { prefix: "/api/admin/vehicles" });
|
||||
await app.register(leaveRequestsRoutes, {
|
||||
prefix: "/api/admin/leave-requests",
|
||||
});
|
||||
await app.register(bankAccountsRoutes, {
|
||||
prefix: "/api/admin/bank-accounts",
|
||||
});
|
||||
await app.register(companySettingsRoutes, {
|
||||
prefix: "/api/admin/company-settings",
|
||||
});
|
||||
await app.register(receivedInvoicesRoutes, {
|
||||
prefix: "/api/admin/received-invoices",
|
||||
});
|
||||
await app.register(dashboardRoutes, { prefix: "/api/admin/dashboard" });
|
||||
await app.register(auditLogRoutes, { prefix: "/api/admin/audit-log" });
|
||||
await app.register(profileRoutes, { prefix: "/api/admin/profile" });
|
||||
await app.register(sessionsRoutes, { prefix: "/api/admin/sessions" });
|
||||
await app.register(totpRoutes, { prefix: "/api/admin/totp" });
|
||||
await app.register(scopeTemplatesRoutes, {
|
||||
prefix: "/api/admin/offers-templates",
|
||||
});
|
||||
await app.register(invoicesPdfRoutes, { prefix: "/api/admin/invoices-pdf" });
|
||||
await app.register(offersPdfRoutes, { prefix: "/api/admin/offers-pdf" });
|
||||
await app.register(projectFilesRoutes, {
|
||||
prefix: "/api/admin/project-files",
|
||||
});
|
||||
|
||||
// --- Health check ---
|
||||
app.get('/api/health', async () => ({ status: 'ok', timestamp: new Date().toISOString() }));
|
||||
app.get("/api/health", async () => ({
|
||||
status: "ok",
|
||||
timestamp: new Date().toISOString(),
|
||||
}));
|
||||
|
||||
// --- Frontend: Vite dev middleware (dev only) ---
|
||||
if (!config.isProduction) {
|
||||
const viteModule = await (Function('return import("vite")')() as Promise<any>);
|
||||
const createViteServer = viteModule.createServer as (opts: any) => Promise<any>;
|
||||
const viteModule = await (Function(
|
||||
'return import("vite")',
|
||||
)() as Promise<any>);
|
||||
const createViteServer = viteModule.createServer as (
|
||||
opts: any,
|
||||
) => Promise<any>;
|
||||
const vite = await createViteServer({
|
||||
server: { middlewareMode: true },
|
||||
appType: 'spa',
|
||||
appType: "spa",
|
||||
});
|
||||
|
||||
app.addHook('onRequest', (request, reply, done) => {
|
||||
if (request.url.startsWith('/api/')) {
|
||||
app.addHook("onRequest", (request, reply, done) => {
|
||||
if (request.url.startsWith("/api/")) {
|
||||
done();
|
||||
return;
|
||||
}
|
||||
@@ -120,8 +149,8 @@ async function start() {
|
||||
});
|
||||
|
||||
app.setNotFoundHandler((request, reply) => {
|
||||
if (request.url.startsWith('/api/')) {
|
||||
return reply.status(404).send({ success: false, error: 'Not found' });
|
||||
if (request.url.startsWith("/api/")) {
|
||||
return reply.status(404).send({ success: false, error: "Not found" });
|
||||
}
|
||||
if (!reply.raw.headersSent) {
|
||||
vite.middlewares(request.raw, reply.raw, () => {
|
||||
@@ -134,18 +163,18 @@ async function start() {
|
||||
|
||||
// --- Frontend: static file serving (production) ---
|
||||
if (config.isProduction) {
|
||||
const fastifyStatic = (await import('@fastify/static')).default;
|
||||
const fastifyStatic = (await import("@fastify/static")).default;
|
||||
await app.register(fastifyStatic, {
|
||||
root: path.join(__dirname, '..', 'dist-client'),
|
||||
prefix: '/',
|
||||
root: path.join(__dirname, "..", "dist-client"),
|
||||
prefix: "/",
|
||||
wildcard: false,
|
||||
});
|
||||
|
||||
app.setNotFoundHandler((request, reply) => {
|
||||
if (request.url.startsWith('/api/')) {
|
||||
return reply.status(404).send({ success: false, error: 'Not found' });
|
||||
if (request.url.startsWith("/api/")) {
|
||||
return reply.status(404).send({ success: false, error: "Not found" });
|
||||
}
|
||||
return reply.sendFile('index.html');
|
||||
return reply.sendFile("index.html");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -163,18 +192,18 @@ async function start() {
|
||||
app.log.info(`${signal} received, shutting down gracefully...`);
|
||||
try {
|
||||
await app.close();
|
||||
const { default: prisma } = await import('./config/database');
|
||||
const { default: prisma } = await import("./config/database");
|
||||
await prisma.$disconnect();
|
||||
app.log.info('Server shut down successfully');
|
||||
app.log.info("Server shut down successfully");
|
||||
process.exit(0);
|
||||
} catch (err) {
|
||||
app.log.error(err, 'Error during shutdown');
|
||||
app.log.error(err, "Error during shutdown");
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
||||
process.on('SIGINT', () => shutdown('SIGINT'));
|
||||
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
||||
process.on("SIGINT", () => shutdown("SIGINT"));
|
||||
}
|
||||
|
||||
start();
|
||||
|
||||
Reference in New Issue
Block a user