feat: wip server folder structure (#4573)

* feat: wip server folder structure

* fix: merge

* fix: wrong merge

* fix: remove unused file

* fix: comment

* fix: lint

* fix: merge

* fix: remove console.log

* fix: metadata graphql arguments broken
This commit is contained in:
Jérémy M
2024-03-20 16:23:46 +01:00
committed by GitHub
parent da12710fe9
commit e5c1309e8c
461 changed files with 1396 additions and 1322 deletions

View File

@ -0,0 +1,86 @@
import { GraphQLResolveInfo } from 'graphql';
import { getGraphQLRateLimiter } from 'graphql-rate-limit';
import { Plugin } from '@envelop/core';
import { useOnResolve } from '@envelop/on-resolve';
import { GraphQLContext } from 'src/engine/api/graphql/graphql-config/graphql-config.service';
export class UnauthenticatedError extends Error {}
export type IdentifyFn<ContextType = ThrottlerContext> = (
context: ContextType,
) => string;
export type ThrottlerPluginOptions = {
identifyFn: IdentifyFn;
ttl?: number;
limit?: number;
transformError?: (message: string) => Error;
onThrottlerError?: (event: {
error: string;
identifier: string;
context: unknown;
info: GraphQLResolveInfo;
}) => void;
};
interface ThrottlerContext extends GraphQLContext {
rateLimiterFn: ReturnType<typeof getGraphQLRateLimiter>;
}
export const useThrottler = (
options: ThrottlerPluginOptions,
): Plugin<ThrottlerContext> => {
const rateLimiterFn = getGraphQLRateLimiter({
identifyContext: options.identifyFn,
});
return {
onPluginInit({ addPlugin }) {
addPlugin(
useOnResolve(async ({ args, root, context, info }) => {
if (options.limit && options.ttl) {
const id = options.identifyFn(context);
const errorMessage = await context.rateLimiterFn(
{ parent: root, args, context, info },
{
max: options?.limit,
window: `${options?.ttl}s`,
message: interpolate('Too much request.', {
id,
}),
},
);
if (errorMessage) {
if (options.onThrottlerError) {
options.onThrottlerError({
error: errorMessage,
identifier: id,
context,
info,
});
}
if (options.transformError) {
throw options.transformError(errorMessage);
}
throw new Error(errorMessage);
}
}
}),
);
},
async onContextBuilding({ extendContext }) {
extendContext({
rateLimiterFn,
});
},
};
};
function interpolate(message: string, args: { [key: string]: string }) {
return message.replace(/\{{([^)]*)\}}/g, (_, key) => args[key.trim()]);
}