feat: implement function management with FunctionEntity, FunctionService, and FunctionController; enhance QueryExecuterService to utilize functions; refactor CommandController and QueryController to extend BaseQueryController; update Vm class to handle functions; remove obsolete log entities
This commit is contained in:
24
src/migrations/1760026715562-functions.ts
Normal file
24
src/migrations/1760026715562-functions.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class Functions1760026715562 implements MigrationInterface {
|
||||||
|
name = "Functions1760026715562";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE \`function\` (\`id\` varchar(36) NOT NULL, \`name\` varchar(255) NOT NULL, \`source\` longtext NOT NULL, \`projectId\` varchar(36) NULL, UNIQUE INDEX \`IDX_FUNCTION_NAME_PROJECT\` (\`name\`, \`projectId\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`function\` ADD CONSTRAINT \`FK_ed63e3acac533604d1d4a21b1d3\` FOREIGN KEY (\`projectId\`) REFERENCES \`project\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`function\` DROP FOREIGN KEY \`FK_ed63e3acac533604d1d4a21b1d3\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP INDEX \`IDX_FUNCTION_NAME_PROJECT\` ON \`function\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE \`function\``);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,6 +9,7 @@ import {
|
|||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
} from "typeorm";
|
} from "typeorm";
|
||||||
import { Database } from "../../databaseManager/entities/database.entity";
|
import { Database } from "../../databaseManager/entities/database.entity";
|
||||||
|
import { FunctionEntity } from "../../query/entities/function.entity";
|
||||||
|
|
||||||
@Entity("project")
|
@Entity("project")
|
||||||
export class Project {
|
export class Project {
|
||||||
@ -27,4 +28,7 @@ export class Project {
|
|||||||
|
|
||||||
@OneToMany(() => Query, (query) => query.project)
|
@OneToMany(() => Query, (query) => query.project)
|
||||||
queries: Query[];
|
queries: Query[];
|
||||||
|
|
||||||
|
@OneToMany(() => FunctionEntity, (functionEntity) => functionEntity.project)
|
||||||
|
functions: FunctionEntity[];
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/project/function/function.controller.ts
Normal file
22
src/project/function/function.controller.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Controller, Inject, Post, UseGuards } from "@nestjs/common";
|
||||||
|
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
|
||||||
|
import { FunctionService } from "./function.service";
|
||||||
|
|
||||||
|
@Controller("functions")
|
||||||
|
@UseGuards(ApiTokenGuard)
|
||||||
|
export class FunctionController {
|
||||||
|
constructor(
|
||||||
|
@Inject(FunctionService)
|
||||||
|
private readonly functionService: FunctionService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@Post("create")
|
||||||
|
async createFunction(projectId: string, name: string, source: string) {
|
||||||
|
return this.functionService.create(projectId, name, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("delete")
|
||||||
|
async deleteFunction(projectId: string, name: string) {
|
||||||
|
return this.functionService.deleteFunction(projectId, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/project/function/function.service.ts
Normal file
65
src/project/function/function.service.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { Inject, Injectable } from "@nestjs/common";
|
||||||
|
import { InjectRepository } from "@nestjs/typeorm";
|
||||||
|
import { FunctionEntity } from "src/query/entities/function.entity";
|
||||||
|
import { In, Repository } from "typeorm";
|
||||||
|
import { ProjectService } from "../project.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FunctionService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(FunctionEntity)
|
||||||
|
private readonly functionRepository: Repository<FunctionEntity>,
|
||||||
|
@Inject(ProjectService)
|
||||||
|
private readonly projectService: ProjectService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async create(
|
||||||
|
projectId: string,
|
||||||
|
name: string,
|
||||||
|
source: string
|
||||||
|
): Promise<FunctionEntity> {
|
||||||
|
const project = await this.projectService.findById(projectId);
|
||||||
|
|
||||||
|
if (!project) {
|
||||||
|
throw new Error("Project not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingFunction = await this.functionRepository.findOne({
|
||||||
|
where: { name, project: { id: projectId } },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingFunction) {
|
||||||
|
existingFunction.source = source;
|
||||||
|
return this.functionRepository.save(existingFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
const functionEntity = this.functionRepository.create({
|
||||||
|
name,
|
||||||
|
source,
|
||||||
|
project,
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.functionRepository.save(functionEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
async findByNames(
|
||||||
|
projectId: string,
|
||||||
|
names: string[]
|
||||||
|
): Promise<FunctionEntity[]> {
|
||||||
|
return this.functionRepository.find({
|
||||||
|
where: { project: { id: projectId }, name: In(names) },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteFunction(projectId: string, name: string): Promise<void> {
|
||||||
|
const functionEntity = await this.functionRepository.findOne({
|
||||||
|
where: { name, project: { id: projectId } },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!functionEntity) {
|
||||||
|
throw new Error("Function not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.functionRepository.remove(functionEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
71
src/query/base/base-query.controller.ts
Normal file
71
src/query/base/base-query.controller.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import {
|
||||||
|
Body,
|
||||||
|
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";
|
||||||
|
|
||||||
|
@UseGuards(ApiTokenGuard)
|
||||||
|
export abstract class BaseQueryController {
|
||||||
|
constructor(
|
||||||
|
@Inject(QueryHandlerService)
|
||||||
|
protected readonly queryHandlerService: QueryHandlerService,
|
||||||
|
@Inject(QueryExecuterService)
|
||||||
|
protected readonly queryExecuterService: QueryExecuterService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
protected abstract getIsCommand(): boolean;
|
||||||
|
|
||||||
|
@Post("create")
|
||||||
|
async createQuery(
|
||||||
|
@Body() queryData: { projectToken: string; source: string }
|
||||||
|
) {
|
||||||
|
return this.queryHandlerService.createQuery(queryData, this.getIsCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
@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>,
|
||||||
|
@Res() res: Response
|
||||||
|
) {
|
||||||
|
const queryResult = await this.queryExecuterService.runQueryQueued(
|
||||||
|
token,
|
||||||
|
query,
|
||||||
|
headers
|
||||||
|
);
|
||||||
|
|
||||||
|
res.status(queryResult?.statusCode || 200);
|
||||||
|
|
||||||
|
if (
|
||||||
|
queryResult?.statusCode === 302 &&
|
||||||
|
queryResult?.headers &&
|
||||||
|
queryResult?.headers["Location"]
|
||||||
|
) {
|
||||||
|
res.redirect(queryResult?.headers["Location"]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(queryResult?.headers || {})) {
|
||||||
|
res.setHeader(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send(queryResult?.response || null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,67 +1,20 @@
|
|||||||
import {
|
import { Controller, Inject } from "@nestjs/common";
|
||||||
Body,
|
|
||||||
Controller,
|
|
||||||
Headers,
|
|
||||||
Inject,
|
|
||||||
Param,
|
|
||||||
Post,
|
|
||||||
Res,
|
|
||||||
UseGuards,
|
|
||||||
} from "@nestjs/common";
|
|
||||||
import { QueryHandlerService } from "../handler/query.handler.service";
|
import { QueryHandlerService } from "../handler/query.handler.service";
|
||||||
import { QueryExecuterService } from "../executer/query.executer.service";
|
import { QueryExecuterService } from "../executer/query.executer.service";
|
||||||
import { Response } from "express";
|
import { BaseQueryController } from "../base/base-query.controller";
|
||||||
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
|
|
||||||
|
|
||||||
@Controller("command")
|
@Controller("command")
|
||||||
@UseGuards(ApiTokenGuard)
|
export class CommandController extends BaseQueryController {
|
||||||
export class CommandController {
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(QueryHandlerService)
|
@Inject(QueryHandlerService)
|
||||||
private readonly queryHandlerService: QueryHandlerService,
|
queryHandlerService: QueryHandlerService,
|
||||||
@Inject(QueryExecuterService)
|
@Inject(QueryExecuterService)
|
||||||
private readonly queryExecuterService: QueryExecuterService
|
queryExecuterService: QueryExecuterService
|
||||||
) {}
|
|
||||||
|
|
||||||
@Post("create")
|
|
||||||
async createQuery(
|
|
||||||
@Body() queryData: { projectToken: string; source: string }
|
|
||||||
) {
|
) {
|
||||||
return this.queryHandlerService.createQuery(queryData, true);
|
super(queryHandlerService, queryExecuterService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post("update/:id")
|
protected getIsCommand(): boolean {
|
||||||
async updateQuery(
|
return true;
|
||||||
@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>,
|
|
||||||
@Res() res: Response
|
|
||||||
) {
|
|
||||||
const queryResult = await this.queryExecuterService.runQueryQueued(
|
|
||||||
token,
|
|
||||||
query,
|
|
||||||
headers
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(queryResult.statusCode);
|
|
||||||
|
|
||||||
if (queryResult.statusCode === 302 && queryResult.headers["Location"]) {
|
|
||||||
res.redirect(queryResult.headers["Location"]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(queryResult.headers)) {
|
|
||||||
res.setHeader(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.send(queryResult.response);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
src/query/entities/function.entity.ts
Normal file
24
src/query/entities/function.entity.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { Project } from "../../project/entities/project.entity";
|
||||||
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
Index,
|
||||||
|
ManyToOne,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
} from "typeorm";
|
||||||
|
|
||||||
|
@Entity("function")
|
||||||
|
@Index("IDX_FUNCTION_NAME_PROJECT", ["name", "project"], { unique: true })
|
||||||
|
export class FunctionEntity {
|
||||||
|
@PrimaryGeneratedColumn("uuid")
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 255 })
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column({ type: "longtext" })
|
||||||
|
source: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => Project, (project) => project.queries)
|
||||||
|
project: Project;
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { Injectable } from "@nestjs/common";
|
import { Inject, Injectable } from "@nestjs/common";
|
||||||
import { InjectRepository } from "@nestjs/typeorm";
|
import { InjectRepository } from "@nestjs/typeorm";
|
||||||
import { Query } from "../entities/query.entity";
|
import { Query } from "../entities/query.entity";
|
||||||
import { Repository } from "typeorm";
|
import { Repository } from "typeorm";
|
||||||
@ -13,6 +13,7 @@ import { DatabaseManagerService } from "src/databaseManager/database/database.ma
|
|||||||
import { InjectQueue } from "@nestjs/bullmq";
|
import { InjectQueue } from "@nestjs/bullmq";
|
||||||
import { QUEUE_NAMES } from "src/queue/constants";
|
import { QUEUE_NAMES } from "src/queue/constants";
|
||||||
import { Queue, QueueEvents } from "bullmq";
|
import { Queue, QueueEvents } from "bullmq";
|
||||||
|
import { FunctionService } from "src/project/function/function.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class QueryExecuterService {
|
export class QueryExecuterService {
|
||||||
@ -21,6 +22,8 @@ export class QueryExecuterService {
|
|||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Query)
|
@InjectRepository(Query)
|
||||||
readonly queryRepository: Repository<Query>,
|
readonly queryRepository: Repository<Query>,
|
||||||
|
@Inject(FunctionService)
|
||||||
|
private readonly functionService: FunctionService,
|
||||||
readonly databaseManagerService: DatabaseManagerService,
|
readonly databaseManagerService: DatabaseManagerService,
|
||||||
@InjectQueue(QUEUE_NAMES.QUERY) private queryQueue: Queue
|
@InjectQueue(QUEUE_NAMES.QUERY) private queryQueue: Queue
|
||||||
) {
|
) {
|
||||||
@ -110,6 +113,16 @@ export class QueryExecuterService {
|
|||||||
|
|
||||||
const moduleNames = importsParsed.filter((imp) => imp.type === "module");
|
const moduleNames = importsParsed.filter((imp) => imp.type === "module");
|
||||||
const pluginNames = importsParsed.filter((imp) => imp.type === "plugin");
|
const pluginNames = importsParsed.filter((imp) => imp.type === "plugin");
|
||||||
|
const functionNames = importsParsed.filter(
|
||||||
|
(imp) => imp.type === "function"
|
||||||
|
);
|
||||||
|
|
||||||
|
const functions = (
|
||||||
|
await this.functionService.findByNames(
|
||||||
|
query.project.id,
|
||||||
|
functionNames.map((fn) => fn.name)
|
||||||
|
)
|
||||||
|
).map((fn) => fn.source);
|
||||||
|
|
||||||
const modules = moduleNames.map((mod) => {
|
const modules = moduleNames.map((mod) => {
|
||||||
if (registeredModules[mod.name]) {
|
if (registeredModules[mod.name]) {
|
||||||
@ -134,24 +147,18 @@ export class QueryExecuterService {
|
|||||||
cpuTimeLimit: BigInt(5e9),
|
cpuTimeLimit: BigInt(5e9),
|
||||||
modules: modules,
|
modules: modules,
|
||||||
plugins: plugins,
|
plugins: plugins,
|
||||||
|
functions: functions,
|
||||||
});
|
});
|
||||||
|
|
||||||
return await vm.init();
|
return await vm.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkResponse(obj: any): obj is QueryResponse {
|
private checkResponse(obj: any): boolean {
|
||||||
return (
|
if (obj?.statusCode && obj.response && typeof obj.statusCode === "number") {
|
||||||
obj !== null &&
|
return true;
|
||||||
typeof obj === "object" &&
|
}
|
||||||
typeof obj.statusCode === "number" &&
|
|
||||||
typeof obj.response === "object" &&
|
return false;
|
||||||
obj.response !== null &&
|
|
||||||
typeof obj.headers === "object" &&
|
|
||||||
obj.headers !== null &&
|
|
||||||
Object.keys(obj.headers).every(
|
|
||||||
(key) => typeof obj.headers[key] === "string"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onModuleDestroy() {
|
async onModuleDestroy() {
|
||||||
|
|||||||
@ -1,67 +1,20 @@
|
|||||||
import {
|
import { Controller, Inject } from "@nestjs/common";
|
||||||
Body,
|
|
||||||
Controller,
|
|
||||||
Headers,
|
|
||||||
Inject,
|
|
||||||
Param,
|
|
||||||
Post,
|
|
||||||
Res,
|
|
||||||
UseGuards,
|
|
||||||
} from "@nestjs/common";
|
|
||||||
import { Response } from "express";
|
|
||||||
import { QueryHandlerService } from "./query.handler.service";
|
import { QueryHandlerService } from "./query.handler.service";
|
||||||
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
|
|
||||||
import { QueryExecuterService } from "../executer/query.executer.service";
|
import { QueryExecuterService } from "../executer/query.executer.service";
|
||||||
|
import { BaseQueryController } from "../base/base-query.controller";
|
||||||
|
|
||||||
@Controller("query")
|
@Controller("query")
|
||||||
@UseGuards(ApiTokenGuard)
|
export class QueryController extends BaseQueryController {
|
||||||
export class QueryController {
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(QueryHandlerService)
|
@Inject(QueryHandlerService)
|
||||||
private readonly queryHandlerService: QueryHandlerService,
|
queryHandlerService: QueryHandlerService,
|
||||||
@Inject(QueryExecuterService)
|
@Inject(QueryExecuterService)
|
||||||
private readonly queryExecuterService: QueryExecuterService
|
queryExecuterService: QueryExecuterService
|
||||||
) {}
|
|
||||||
|
|
||||||
@Post("create")
|
|
||||||
async createQuery(
|
|
||||||
@Body() queryData: { projectToken: string; source: string }
|
|
||||||
) {
|
) {
|
||||||
return this.queryHandlerService.createQuery(queryData);
|
super(queryHandlerService, queryExecuterService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post("update/:id")
|
protected getIsCommand(): boolean {
|
||||||
async updateQuery(
|
return false;
|
||||||
@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>,
|
|
||||||
@Res() res: Response
|
|
||||||
) {
|
|
||||||
const queryResult = await this.queryExecuterService.runQueryQueued(
|
|
||||||
token,
|
|
||||||
query,
|
|
||||||
headers
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(queryResult.statusCode);
|
|
||||||
|
|
||||||
if (queryResult.statusCode === 302 && queryResult.headers["Location"]) {
|
|
||||||
res.redirect(queryResult.headers["Location"]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(queryResult.headers)) {
|
|
||||||
res.setHeader(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.send(queryResult.response);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
|
||||||
import { LogRecord } from "../logs.type";
|
|
||||||
|
|
||||||
@Entity("logs")
|
|
||||||
export class LogEntity {
|
|
||||||
@PrimaryGeneratedColumn("uuid")
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
@Column({
|
|
||||||
type: "longtext",
|
|
||||||
nullable: false,
|
|
||||||
transformer: {
|
|
||||||
to: (value: any) => JSON.stringify(value),
|
|
||||||
from: (value: any) => JSON.parse(value),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
record: LogRecord;
|
|
||||||
|
|
||||||
// TODO: projectId
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
export type LogLevel = "DEBUG" | "INFO" | "WARN" | "ERROR" | "FATAL";
|
|
||||||
|
|
||||||
export type LogLine = {
|
|
||||||
timestamp: string;
|
|
||||||
message: string;
|
|
||||||
level: LogLevel;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type LogRecord = {
|
|
||||||
id: string;
|
|
||||||
lines: LogLine[];
|
|
||||||
};
|
|
||||||
@ -9,6 +9,9 @@ import { DatabaseManagerModule } from "src/databaseManager/database.manager.modu
|
|||||||
import { CommandController } from "./command/command.controller";
|
import { CommandController } from "./command/command.controller";
|
||||||
import { ApiModule } from "src/api/api.module";
|
import { ApiModule } from "src/api/api.module";
|
||||||
import { QueueModule } from "src/queue/queue.module";
|
import { QueueModule } from "src/queue/queue.module";
|
||||||
|
import { FunctionEntity } from "./entities/function.entity";
|
||||||
|
import { FunctionService } from "src/project/function/function.service";
|
||||||
|
import { FunctionController } from "src/project/function/function.controller";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -16,10 +19,10 @@ import { QueueModule } from "src/queue/queue.module";
|
|||||||
forwardRef(() => DatabaseManagerModule),
|
forwardRef(() => DatabaseManagerModule),
|
||||||
forwardRef(() => ApiModule),
|
forwardRef(() => ApiModule),
|
||||||
forwardRef(() => QueueModule),
|
forwardRef(() => QueueModule),
|
||||||
TypeOrmModule.forFeature([Query]),
|
TypeOrmModule.forFeature([Query, FunctionEntity]),
|
||||||
],
|
],
|
||||||
controllers: [QueryController, CommandController],
|
controllers: [QueryController, CommandController, FunctionController],
|
||||||
providers: [QueryExecuterService, QueryHandlerService],
|
providers: [QueryExecuterService, QueryHandlerService, FunctionService],
|
||||||
exports: [QueryExecuterService, TypeOrmModule],
|
exports: [QueryExecuterService, TypeOrmModule],
|
||||||
})
|
})
|
||||||
export class QueryModule {}
|
export class QueryModule {}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export class Vm {
|
|||||||
private context: any;
|
private context: any;
|
||||||
private jail: any;
|
private jail: any;
|
||||||
private plugins: Plugin[];
|
private plugins: Plugin[];
|
||||||
|
private functions: string[];
|
||||||
private isolate: ivm.Isolate;
|
private isolate: ivm.Isolate;
|
||||||
private timeLimit?: bigint;
|
private timeLimit?: bigint;
|
||||||
private cpuTimeLimit?: bigint;
|
private cpuTimeLimit?: bigint;
|
||||||
@ -19,12 +20,14 @@ export class Vm {
|
|||||||
cpuTimeLimit?: bigint;
|
cpuTimeLimit?: bigint;
|
||||||
modules: VModule[];
|
modules: VModule[];
|
||||||
plugins: Plugin[];
|
plugins: Plugin[];
|
||||||
|
functions: string[];
|
||||||
}) {
|
}) {
|
||||||
this.memoryLimit = configs.memoryLimit;
|
this.memoryLimit = configs.memoryLimit;
|
||||||
this.modules = configs.modules;
|
this.modules = configs.modules;
|
||||||
this.plugins = configs.plugins;
|
this.plugins = configs.plugins;
|
||||||
this.timeLimit = configs.timeLimit;
|
this.timeLimit = configs.timeLimit;
|
||||||
this.cpuTimeLimit = configs.cpuTimeLimit;
|
this.cpuTimeLimit = configs.cpuTimeLimit;
|
||||||
|
this.functions = configs.functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
async init(): Promise<Vm> {
|
async init(): Promise<Vm> {
|
||||||
@ -38,6 +41,10 @@ export class Vm {
|
|||||||
await this.context.eval(mod.getSource());
|
await this.context.eval(mod.getSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const fn of this.functions) {
|
||||||
|
await this.context.eval(fn);
|
||||||
|
}
|
||||||
|
|
||||||
for (const plugin of this.plugins) {
|
for (const plugin of this.plugins) {
|
||||||
const pluginName = plugin.getName();
|
const pluginName = plugin.getName();
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,6 @@ export const registeredModules = {
|
|||||||
|
|
||||||
export type QueryResponse = {
|
export type QueryResponse = {
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
response: Record<string, any>;
|
response: any;
|
||||||
headers: Record<string, string>;
|
headers: Record<string, string>;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user