EvoCalculator.Client2/apps/api/src/proxy/proxy.controller.ts
2024-03-04 16:42:14 +03:00

108 lines
2.8 KiB
TypeScript

import { queryTTL } from './lib/config';
import type { GQLRequest } from './types';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import {
All,
Controller,
Delete,
Get,
HttpException,
HttpStatus,
Inject,
Query,
Req,
Res,
} from '@nestjs/common';
import type { Cache } from 'cache-manager';
import { FastifyReply, FastifyRequest } from 'fastify';
import { env } from 'src/config/env';
type RedisStore = Omit<Cache, 'set'> & {
set: (key: string, value: unknown, { ttl }: { ttl: number }) => Promise<void>;
};
@Controller('proxy')
export class ProxyController {
constructor(
@Inject(CACHE_MANAGER) private readonly cacheManager: RedisStore,
) {}
@All('/graphql')
public async graphql(@Req() req: FastifyRequest, @Res() reply: FastifyReply) {
const { operationName, query, variables } = req.body as GQLRequest;
const key = `${operationName} ${JSON.stringify(variables)}`;
const cached = await this.cacheManager.get(key);
if (cached) return reply.send(cached);
const response = await fetch(env.URL_CRM_GRAPHQL_DIRECT, {
body: JSON.stringify({ operationName, query, variables }),
headers: {
Authorization: req.headers.authorization,
'Content-Type': 'application/json',
Cookie: req.headers.cookie,
},
method: req.method,
});
if (!response.ok)
throw new HttpException(
response.statusText,
response.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
const data = await response.json();
const ttl = queryTTL[operationName];
if (data && ttl !== false)
await this.cacheManager.set(key, data, { ttl: ttl || env.CACHE_TTL });
return reply.send(data);
}
@Get('/queries')
public async getQueriesList(
@Req() req: FastifyRequest,
@Res() reply: FastifyReply,
) {
const list = await this.cacheManager.store.keys('*');
const res = (Object.keys(queryTTL) as Array<keyof typeof queryTTL>).reduce(
(acc, queryName) => {
const queries = list.filter((x) => x.split(' ').at(0) === queryName);
const ttl = queryTTL[queryName];
acc[queryName] = { queries, ttl };
return acc;
},
{} as Record<string, unknown>,
);
return reply.send(res);
}
@Delete('delete-query')
public async deleteQuery(
@Query('queryName') queryName: string,
@Res() reply: FastifyReply,
) {
try {
await this.cacheManager.del(queryName);
return reply.send('ok');
} catch (error) {
throw new HttpException(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@Delete('flush-all')
public async flushAll(@Res() reply: FastifyReply) {
try {
await this.cacheManager.reset();
return reply.send('ok');
} catch (error) {
throw new HttpException(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}