project setup with core files including configuration, package management, and basic structure. Added .gitignore, README, and various TypeScript types for CMS components. Implemented initial components and layouts for the application.
This commit is contained in:
119
middlelayer/index.ts
Normal file
119
middlelayer/index.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import { ApolloServer } from "@apollo/server";
|
||||
import { startStandaloneServer } from "@apollo/server/standalone";
|
||||
import { createServer } from "http";
|
||||
import { typeDefs } from "./schema.js";
|
||||
import { resolvers } from "./resolvers.js";
|
||||
import { queryComplexityPlugin } from "./plugins/queryComplexity.js";
|
||||
import { createResponseCachePlugin } from "./plugins/responseCache.js";
|
||||
import {
|
||||
monitoringPlugin,
|
||||
queryComplexityMonitoringPlugin,
|
||||
} from "./plugins/monitoring.js";
|
||||
import { createContext, type GraphQLContext } from "./utils/dataloaders.js";
|
||||
import { logger } from "./monitoring/logger.js";
|
||||
import { getMetrics } from "./monitoring/metrics.js";
|
||||
import { extractTokenFromHeader } from "./auth/jwt.js";
|
||||
import { userService } from "./auth/userService.js";
|
||||
|
||||
const PORT = process.env.PORT ? parseInt(process.env.PORT) : 4000;
|
||||
const METRICS_PORT = process.env.METRICS_PORT
|
||||
? parseInt(process.env.METRICS_PORT)
|
||||
: 9090;
|
||||
|
||||
// Konfiguration aus Environment Variables
|
||||
const MAX_QUERY_COMPLEXITY = process.env.MAX_QUERY_COMPLEXITY
|
||||
? parseInt(process.env.MAX_QUERY_COMPLEXITY)
|
||||
: 1000;
|
||||
|
||||
/**
|
||||
* Startet einen separaten HTTP-Server für Metrics (Prometheus)
|
||||
*/
|
||||
function startMetricsServer() {
|
||||
const server = createServer(async (req, res) => {
|
||||
if (req.url === "/metrics" && req.method === "GET") {
|
||||
try {
|
||||
const metrics = await getMetrics();
|
||||
res.writeHead(200, { "Content-Type": "text/plain; version=0.0.4" });
|
||||
res.end(metrics);
|
||||
} catch (error) {
|
||||
logger.error("Failed to get metrics", { error });
|
||||
res.writeHead(500, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify({ error: "Failed to get metrics" }));
|
||||
}
|
||||
} else if (req.url === "/health" && req.method === "GET") {
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify({ status: "ok", service: "graphql-middlelayer" }));
|
||||
} else {
|
||||
res.writeHead(404, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify({ error: "Not found" }));
|
||||
}
|
||||
});
|
||||
|
||||
server.listen(METRICS_PORT, () => {
|
||||
logger.info(
|
||||
`📊 Metrics Server läuft auf: http://localhost:${METRICS_PORT}/metrics`
|
||||
);
|
||||
logger.info(
|
||||
`❤️ Health Check verfügbar unter: http://localhost:${METRICS_PORT}/health`
|
||||
);
|
||||
});
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
async function startServer() {
|
||||
const server = new ApolloServer<GraphQLContext>({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
plugins: [
|
||||
// Monitoring (muss zuerst sein für vollständiges Tracking)
|
||||
monitoringPlugin(),
|
||||
queryComplexityMonitoringPlugin(),
|
||||
// Query Complexity Limit
|
||||
queryComplexityPlugin({
|
||||
maxComplexity: MAX_QUERY_COMPLEXITY,
|
||||
defaultComplexity: 1,
|
||||
}),
|
||||
// Response Caching
|
||||
createResponseCachePlugin(),
|
||||
],
|
||||
});
|
||||
|
||||
const { url } = await startStandaloneServer(server, {
|
||||
listen: { port: PORT },
|
||||
context: async ({ req }) => {
|
||||
// Extrahiere User aus Authorization Header
|
||||
let user = null;
|
||||
const authHeader = req.headers.authorization;
|
||||
const token = extractTokenFromHeader(authHeader || null);
|
||||
|
||||
if (token) {
|
||||
try {
|
||||
user = await userService.getUserFromToken(token);
|
||||
} catch (error) {
|
||||
logger.warn("Token verification failed", { error });
|
||||
}
|
||||
}
|
||||
|
||||
// Erstelle Context mit Dataloadern und User
|
||||
return createContext(user);
|
||||
},
|
||||
});
|
||||
|
||||
// Starte Metrics Server
|
||||
startMetricsServer();
|
||||
|
||||
logger.info(`🚀 GraphQL Middlelayer läuft auf: ${url}`);
|
||||
logger.info(`📊 GraphQL Playground verfügbar unter: ${url}`);
|
||||
logger.info(`⚡ Query Complexity Limit: ${MAX_QUERY_COMPLEXITY}`);
|
||||
logger.info(`💾 Response Caching: Aktiviert`);
|
||||
logger.info(`🔄 Dataloader: Aktiviert`);
|
||||
logger.info(
|
||||
`📈 Monitoring: Aktiviert (Structured Logging, Prometheus, Tracing)`
|
||||
);
|
||||
}
|
||||
|
||||
startServer().catch((error) => {
|
||||
logger.error("Fehler beim Starten des Servers", { error });
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user