108 lines
2.8 KiB
TypeScript
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);
|
|
}
|
|
}
|
|
}
|