Import source: backend/src/app

Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
arsam
2026-09-18 23:09:12 +03:30
parent 4030ac5133
commit feb86628b0
+120
View File
@@ -0,0 +1,120 @@
import Fastify from "fastify";
import cors from "@fastify/cors";
import helmet from "@fastify/helmet";
import jwt from "@fastify/jwt";
import {
serializerCompiler,
validatorCompiler,
ZodTypeProvider,
} from "fastify-type-provider-zod";
import { env } from "./config/env.js";
import { prismaPlugin } from "./plugins/prisma.js";
import { errorHandler } from "./plugins/error-handler.js";
import { fail } from "./lib/envelope.js";
import { authRoutes } from "./routes/auth.js";
import { websiteRoutes } from "./routes/websites.js";
import { domainRoutes } from "./routes/domains.js";
import { panelRoutes } from "./routes/panel.js";
import { moduleRoutes } from "./routes/modules.js";
export function buildApp() {
const app = Fastify({
logger:
env.NODE_ENV === "development"
? {
transport: { target: "pino-pretty" },
}
: false,
}).withTypeProvider<ZodTypeProvider>();
// Register JSON schemas compilers for Zod
app.setValidatorCompiler(validatorCompiler);
app.setSerializerCompiler(serializerCompiler);
app.removeContentTypeParser("application/json");
app.addContentTypeParser(
"application/json",
{ parseAs: "string" },
(_request, body, done) => {
const text = typeof body === "string" ? body : body.toString("utf8");
if (text.trim() === "") {
done(null, undefined);
return;
}
try {
done(null, JSON.parse(text));
} catch (error) {
done(error as Error, undefined);
}
},
);
// Security Plugins
app.register(helmet);
app.register(cors, { origin: true, credentials: true });
app.register(jwt, { secret: env.JWT_SECRET });
// Custom Plugins
app.register(prismaPlugin);
app.setErrorHandler(errorHandler);
app.get("/api/rate-limited", async (request, reply) =>
fail(
request,
reply,
429,
{
code: "RATE_LIMIT_ERROR",
message: "Too many requests. Please try again later.",
},
{ rateLimit: { limit: 5, remaining: 0, reset: 100 } },
),
);
app.get("/api/simulate-500", async () => {
throw new Error("Internal server error simulated successfully.");
});
app.get("/api/auth/login", async (request, reply) =>
fail(request, reply, 405, {
code: "METHOD_NOT_ALLOWED",
message: "GET is not allowed for this endpoint.",
}),
);
app.register(authRoutes);
app.register(websiteRoutes);
app.register(domainRoutes);
app.register(panelRoutes);
app.register(moduleRoutes);
// Health check route
app.get("/health", async (request, reply) => {
try {
// Verify database connection using Prisma
await app.prisma.$queryRaw`SELECT 1`;
return {
status: "ok",
database: "connected",
};
} catch (err: unknown) {
app.log.error(err);
const message = err instanceof Error ? err.message : String(err);
return reply.status(500).send({
status: "error",
database: "disconnected",
message,
});
}
});
app.setNotFoundHandler((request, reply) =>
fail(request, reply, 404, {
code: "NOT_FOUND",
message: `Route ${request.method} ${request.url} was not found.`,
}),
);
return app;
}