feat: implement command functionality with new CommandController, update Query entity, and enhance query execution with headers support
This commit is contained in:
15
src/migrations/1759387204103-commands.ts
Normal file
15
src/migrations/1759387204103-commands.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class Commands1759387204103 implements MigrationInterface {
|
||||
name = "Commands1759387204103";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE \`query\` ADD \`isCommand\` tinyint NOT NULL DEFAULT '0'`
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE \`query\` DROP COLUMN \`isCommand\``);
|
||||
}
|
||||
}
|
||||
37
src/query/command/command.controller.ts
Normal file
37
src/query/command/command.controller.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { Body, Controller, Headers, Inject, Param, Post } from "@nestjs/common";
|
||||
import { QueryHandlerService } from "../handler/query.handler.service";
|
||||
import { QueryExecuterService } from "../executer/query.executer.service";
|
||||
|
||||
@Controller("command")
|
||||
export class CommandController {
|
||||
constructor(
|
||||
@Inject(QueryHandlerService)
|
||||
private readonly queryHandlerService: QueryHandlerService,
|
||||
@Inject(QueryExecuterService)
|
||||
private readonly queryExecuterService: QueryExecuterService
|
||||
) {}
|
||||
|
||||
@Post("create")
|
||||
async createQuery(
|
||||
@Body() queryData: { projectToken: string; source: string }
|
||||
) {
|
||||
return this.queryHandlerService.createQuery(queryData, true);
|
||||
}
|
||||
|
||||
@Post("update/:id")
|
||||
async updateQuery(
|
||||
@Body() updateData: Partial<{ source: string }>,
|
||||
@Inject("id") id: string
|
||||
) {
|
||||
return this.queryHandlerService.updateQuery(id, updateData);
|
||||
}
|
||||
|
||||
@Post("/run/:token")
|
||||
async runQuery(
|
||||
@Param("token") token: string,
|
||||
@Body() query: Record<string, any>,
|
||||
@Headers() headers: Record<string, any>
|
||||
) {
|
||||
return this.queryExecuterService.runQuery(token, query, headers);
|
||||
}
|
||||
}
|
||||
@ -14,4 +14,7 @@ export class Query {
|
||||
|
||||
@Column({ type: "tinyint", default: 1 })
|
||||
isActive: number;
|
||||
|
||||
@Column({ type: "tinyint", default: 0 })
|
||||
isCommand: number;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Body, Controller, Inject, Param, Post } from "@nestjs/common";
|
||||
import { Body, Controller, Headers, Inject, Param, Post } from "@nestjs/common";
|
||||
import { QueryExecuterService } from "./query.executer.service";
|
||||
|
||||
@Controller("query")
|
||||
@ -11,8 +11,9 @@ export class QueryExecuterController {
|
||||
@Post("/run/:token")
|
||||
async runQuery(
|
||||
@Param("token") token: string,
|
||||
@Body() query: Record<string, any>
|
||||
@Body() query: Record<string, any>,
|
||||
@Headers() headers: Record<string, any>
|
||||
) {
|
||||
return this.queryExecuterService.runQuery(token, query);
|
||||
return this.queryExecuterService.runQuery(token, query, headers);
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,7 +34,11 @@ export class QueryExecuterService {
|
||||
.trim();
|
||||
}
|
||||
|
||||
async runQuery(token: string, queryData: any) {
|
||||
async runQuery(
|
||||
token: string,
|
||||
queryData: any,
|
||||
headers: Record<string, any> = {}
|
||||
) {
|
||||
const query = await this.queryRepository.findOne({
|
||||
where: { id: token },
|
||||
relations: ["project"],
|
||||
@ -47,7 +51,8 @@ export class QueryExecuterService {
|
||||
const vm = await this.createVm(query);
|
||||
const result = await vm.runScript(
|
||||
this.clearImports(query.source),
|
||||
queryData
|
||||
queryData,
|
||||
headers
|
||||
);
|
||||
|
||||
return { message: "Query executed", result, query: queryData };
|
||||
|
||||
@ -13,7 +13,10 @@ export class QueryHandlerService {
|
||||
private readonly projectService: ProjectService
|
||||
) {}
|
||||
|
||||
async createQuery(queryData: { projectToken: string; source: string }) {
|
||||
async createQuery(
|
||||
queryData: { projectToken: string; source: string },
|
||||
isCommand = false
|
||||
) {
|
||||
const project = await this.projectService.findById(queryData.projectToken);
|
||||
|
||||
if (!project) {
|
||||
@ -21,6 +24,7 @@ export class QueryHandlerService {
|
||||
}
|
||||
|
||||
queryData["project"] = project;
|
||||
queryData["isCommand"] = isCommand ? 1 : 0;
|
||||
delete queryData.projectToken;
|
||||
|
||||
const query = this.queryRepository.create(queryData);
|
||||
|
||||
@ -7,6 +7,7 @@ import { QueryExecuterService } from "./executer/query.executer.service";
|
||||
import { QueryHandlerService } from "./handler/query.handler.service";
|
||||
import { ProjectModule } from "src/project/project.module";
|
||||
import { DatabaseManagerModule } from "src/databaseManager/database.manager.module";
|
||||
import { CommandController } from "./command/command.controller";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -14,7 +15,11 @@ import { DatabaseManagerModule } from "src/databaseManager/database.manager.modu
|
||||
forwardRef(() => DatabaseManagerModule),
|
||||
TypeOrmModule.forFeature([Query]),
|
||||
],
|
||||
controllers: [QueryExecuterController, QueryHandlerController],
|
||||
controllers: [
|
||||
QueryExecuterController,
|
||||
QueryHandlerController,
|
||||
CommandController,
|
||||
],
|
||||
providers: [QueryExecuterService, QueryHandlerService],
|
||||
})
|
||||
export class QueryModule {}
|
||||
|
||||
25
src/vm/plugins/query.plugin.ts
Normal file
25
src/vm/plugins/query.plugin.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { QueryExecuterService } from "../../query/executer/query.executer.service";
|
||||
import { Query } from "../../query/entities/query.entity";
|
||||
import { Plugin } from "../plugin.class";
|
||||
|
||||
export class QueryPlugin extends Plugin {
|
||||
constructor(
|
||||
name: string,
|
||||
private query: Query,
|
||||
private QueryExecuterService: QueryExecuterService
|
||||
) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
static async init(query: Query, queryExecuterService: QueryExecuterService) {
|
||||
return new QueryPlugin("query", query, queryExecuterService);
|
||||
}
|
||||
|
||||
async run(data): Promise<any> {
|
||||
return await this.QueryExecuterService.runQuery(this.query.id, data);
|
||||
}
|
||||
|
||||
onFinish() {
|
||||
// No resources to clean up
|
||||
}
|
||||
}
|
||||
@ -47,7 +47,11 @@ export class Vm {
|
||||
this.jail.setSync(name, func);
|
||||
}
|
||||
|
||||
async runScript(script: string, args: Record<string, any>): Promise<any> {
|
||||
async runScript(
|
||||
script: string,
|
||||
args: Record<string, any>,
|
||||
headers: Record<string, any>
|
||||
): Promise<any> {
|
||||
let resolvePromise: (value: any) => void;
|
||||
let rejectPromise: (reason?: any) => void;
|
||||
|
||||
@ -76,7 +80,9 @@ export class Vm {
|
||||
(async () => {
|
||||
${script}
|
||||
try {
|
||||
const result = await main(${JSON.stringify(args)});
|
||||
const result = await main(${JSON.stringify(
|
||||
args
|
||||
)}, ${JSON.stringify(headers)});
|
||||
returnResult(JSON.stringify(result))
|
||||
} catch (e) {
|
||||
error(e)
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import { QueryExecuterService } from "src/query/executer/query.executer.service";
|
||||
import { DatabasePlugin } from "./plugins/database.plugin";
|
||||
import { Query } from "src/query/entities/query.entity";
|
||||
import { QueryPlugin } from "./plugins/query.plugin";
|
||||
|
||||
export const registeredPlugins = {
|
||||
db: async (service: QueryExecuterService, query: Query) => {
|
||||
const databaseConnection =
|
||||
await service.databaseManagerService.getConnectionOptions(
|
||||
query.project.id
|
||||
query.project.id,
|
||||
query.isCommand == 0
|
||||
);
|
||||
|
||||
if (!databaseConnection) {
|
||||
@ -15,6 +17,12 @@ export const registeredPlugins = {
|
||||
|
||||
return DatabasePlugin.init("db", databaseConnection);
|
||||
},
|
||||
query: async (service: QueryExecuterService, query: Query) => {
|
||||
return QueryPlugin.init(query, service);
|
||||
},
|
||||
command: async (service: QueryExecuterService, query: Query) => {
|
||||
return QueryPlugin.init(query, service);
|
||||
},
|
||||
};
|
||||
|
||||
export const registeredModules = {
|
||||
|
||||
@ -9,9 +9,11 @@ function createSQL(id) {
|
||||
return squel.select().from("test").where("id = ?", id).toString();
|
||||
}
|
||||
|
||||
async function main(input) {
|
||||
async function main(input, headers) {
|
||||
const sql = createSQL(input.id);
|
||||
const res = await asyncCall(db, sql);
|
||||
|
||||
log(headers);
|
||||
|
||||
return { test: 1, array: [1, 2, [{ id: 1, name: "Test" }]] };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user