68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
import type { ApolloServerPlugin } from "@apollo/server";
|
|
import { getComplexity, simpleEstimator } from "graphql-query-complexity";
|
|
import { GraphQLError } from "graphql";
|
|
|
|
interface QueryComplexityPluginOptions {
|
|
maxComplexity?: number;
|
|
defaultComplexity?: number;
|
|
}
|
|
|
|
/**
|
|
* Apollo Server Plugin für Query Complexity Limits
|
|
* Verhindert zu komplexe Queries, die das System überlasten könnten
|
|
*/
|
|
export const queryComplexityPlugin = (
|
|
options: QueryComplexityPluginOptions = {}
|
|
): ApolloServerPlugin => {
|
|
const maxComplexity = options.maxComplexity ?? 1000;
|
|
const defaultComplexity = options.defaultComplexity ?? 1;
|
|
|
|
return {
|
|
async requestDidStart() {
|
|
return {
|
|
async didResolveOperation({ request, document, schema }) {
|
|
if (!schema) return;
|
|
|
|
try {
|
|
const complexity = getComplexity({
|
|
schema,
|
|
operationName: request.operationName || undefined,
|
|
query: document,
|
|
variables: request.variables || {},
|
|
estimators: [
|
|
// Basis-Komplexität für jeden Field
|
|
simpleEstimator({ defaultComplexity }),
|
|
],
|
|
});
|
|
|
|
// Speichere Complexity im Request für Monitoring
|
|
(request as any).complexity = complexity;
|
|
|
|
if (complexity > maxComplexity) {
|
|
throw new GraphQLError(
|
|
`Query zu komplex (${complexity}). Maximum: ${maxComplexity}`,
|
|
{
|
|
extensions: {
|
|
code: "QUERY_TOO_COMPLEX",
|
|
complexity,
|
|
maxComplexity,
|
|
},
|
|
}
|
|
);
|
|
}
|
|
} catch (error: any) {
|
|
// Wenn es ein Schema-Realm-Problem gibt, logge es aber blockiere nicht
|
|
if (error.message?.includes("another module or realm")) {
|
|
console.warn(
|
|
"[Query Complexity] Schema-Realm-Konflikt, Complexity-Check übersprungen"
|
|
);
|
|
return;
|
|
}
|
|
throw error;
|
|
}
|
|
},
|
|
};
|
|
},
|
|
};
|
|
};
|