Files
few-line-engine/src/query/base/base-query.controller.ts

137 lines
3.8 KiB
TypeScript

import {
Body,
Delete,
Headers,
Inject,
Param,
Post,
Res,
UseGuards,
} from "@nestjs/common";
import { Response } from "express";
import { QueryHandlerService } from "../handler/query.handler.service";
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
import { QueryExecuterService } from "../executer/query.executer.service";
import { QueryGuard } from "src/query/guards/query.guard";
import { LoggerService } from "../logger/logger.service";
import { TLogType } from "../logger/logger.types";
import { QueryResponse } from "src/vm/vm.constants";
@UseGuards(ApiTokenGuard)
export abstract class BaseQueryController {
constructor(
@Inject(QueryHandlerService)
protected readonly queryHandlerService: QueryHandlerService,
@Inject(QueryExecuterService)
protected readonly queryExecuterService: QueryExecuterService,
@Inject(LoggerService)
protected readonly loggerService: LoggerService
) {}
protected abstract getIsCommand(): boolean;
@Post("create")
async createQuery(
@Body() queryData: { projectToken: string; source: string }
) {
return this.queryHandlerService.createQuery(queryData, this.getIsCommand());
}
@Post("update/:id")
@UseGuards(QueryGuard)
async updateQuery(
@Body() updateData: Partial<{ source: string }>,
@Param("id") id: string
) {
return this.queryHandlerService.updateQuery(id, updateData);
}
@Post("/run/:id")
@UseGuards(QueryGuard)
async runQuery(
@Param("id") id: string,
@Body() query: Record<string, any>,
@Headers() headers: Record<string, any>,
@Res() res: Response
) {
let queryResult: QueryResponse;
const loggerTraceId =
headers["x-trace-id"] || LoggerService.generateTraceId();
const log = LoggerService.log(
{
traceId: loggerTraceId,
startTime: new Date().getTime(),
payload: query,
headers: headers,
cookies: headers.cookie,
url: `/run/${id}`,
response: null,
content: [],
},
{ content: "", type: TLogType.info, timeStamp: new Date().getTime() }
);
try {
queryResult = await this.queryExecuterService.runQueryQueued(
id,
query,
log,
headers,
headers.cookie.split("; ").reduce((acc, cookie) => {
const [key, value] = cookie.split("=");
acc[key] = value;
return acc;
}, {})
);
} catch (error) {
log.content.push({
content: `Query execution failed: ${error.message}`,
type: TLogType.error,
timeStamp: new Date().getTime(),
});
log.endTime = new Date().getTime();
await this.loggerService.create(log.traceId, log);
res.status(500).send({ error: "Internal Server Error" });
return;
}
if (queryResult?.log) {
queryResult.log.endTime = new Date().getTime();
const res = JSON.parse(JSON.stringify(queryResult));
delete res.log;
queryResult.log.response = res;
await this.loggerService.create(queryResult.log.traceId, queryResult.log);
}
res.status(queryResult?.statusCode || 200);
if (queryResult?.cookies) {
for (const [key, value] of Object.entries(queryResult?.cookies || {})) {
res.cookie(key, value);
}
}
if (
queryResult?.redirect ||
(queryResult?.statusCode === 302 &&
queryResult?.headers &&
queryResult?.headers["Location"])
) {
res.redirect(queryResult?.redirect || queryResult?.headers["Location"]);
return;
}
for (const [key, value] of Object.entries(queryResult?.headers || {})) {
res.setHeader(key, value);
}
res.send(queryResult?.response || null);
}
@Delete("/delete/:id")
@UseGuards(QueryGuard)
async deleteQuery(@Param("id") id: string) {
return this.queryHandlerService.deleteQuery(id);
}
}