feat: enhance query handling with modules and plugins
- Added ManyToMany relationship for plugins in Query entity. - Updated QueryExecuterController to accept structured query data. - Enhanced QueryExecuterService to support plugin initialization and execution. - Implemented QueryHandlerService methods for creating and updating queries, modules, and plugins. - Introduced new endpoints for creating and adding modules and plugins to queries. - Created Plugin base class and DatabasePlugin implementation for database interactions. - Updated VM class to integrate plugin functionality during script execution. - Added test cases for project, query, module, and plugin operations.
This commit is contained in:
@ -34,9 +34,11 @@
|
|||||||
"@nestjs/core": "^9.0.0",
|
"@nestjs/core": "^9.0.0",
|
||||||
"@nestjs/platform-express": "^9.0.0",
|
"@nestjs/platform-express": "^9.0.0",
|
||||||
"@nestjs/typeorm": "^11.0.0",
|
"@nestjs/typeorm": "^11.0.0",
|
||||||
|
"axios": "^1.12.2",
|
||||||
"isolated-vm": "^6.0.1",
|
"isolated-vm": "^6.0.1",
|
||||||
"mariadb": "^3.4.5",
|
"mariadb": "^3.4.5",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
|
"mysql2": "^3.15.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rxjs": "^7.2.0",
|
"rxjs": "^7.2.0",
|
||||||
"squel": "^5.13.0",
|
"squel": "^5.13.0",
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { TypeOrmModule } from "@nestjs/typeorm";
|
|||||||
import { ConfigModule } from "@nestjs/config";
|
import { ConfigModule } from "@nestjs/config";
|
||||||
import { TestModule } from "../test/test.module";
|
import { TestModule } from "../test/test.module";
|
||||||
import { ApiModule } from "../api/api.module";
|
import { ApiModule } from "../api/api.module";
|
||||||
|
import { QueryModule } from "src/query/query.module";
|
||||||
|
import { ProjectModule } from "src/project/project.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -24,6 +26,8 @@ import { ApiModule } from "../api/api.module";
|
|||||||
autoLoadEntities: true,
|
autoLoadEntities: true,
|
||||||
}),
|
}),
|
||||||
ApiModule,
|
ApiModule,
|
||||||
|
ProjectModule,
|
||||||
|
QueryModule,
|
||||||
TestModule,
|
TestModule,
|
||||||
],
|
],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
|
|||||||
14
src/migrations/1758401762034-ModulesAndPluigns.ts
Normal file
14
src/migrations/1758401762034-ModulesAndPluigns.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class ModulesAndPluigns1758401762034 implements MigrationInterface {
|
||||||
|
name = 'ModulesAndPluigns1758401762034'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE \`plugin\` (\`id\` varchar(36) NOT NULL, \`class\` varchar(255) NOT NULL, \`name\` varchar(255) NOT NULL, \`config\` varchar(255) NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE \`plugin\``);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,10 +2,12 @@ import { Module } from "@nestjs/common";
|
|||||||
import { TypeOrmModule } from "@nestjs/typeorm";
|
import { TypeOrmModule } from "@nestjs/typeorm";
|
||||||
import { Project } from "./entities/project.entity";
|
import { Project } from "./entities/project.entity";
|
||||||
import { ProjectService } from "./project.service";
|
import { ProjectService } from "./project.service";
|
||||||
|
import { ProjectController } from "./project.controller";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([Project])],
|
imports: [TypeOrmModule.forFeature([Project])],
|
||||||
controllers: [],
|
controllers: [ProjectController],
|
||||||
providers: [ProjectService],
|
providers: [ProjectService],
|
||||||
|
exports: [ProjectService],
|
||||||
})
|
})
|
||||||
export class ProjectModule {}
|
export class ProjectModule {}
|
||||||
|
|||||||
@ -14,4 +14,8 @@ export class ProjectService {
|
|||||||
const project = this.projectRepository.create({ name });
|
const project = this.projectRepository.create({ name });
|
||||||
return this.projectRepository.save(project);
|
return this.projectRepository.save(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
findByToken(token: string) {
|
||||||
|
return this.projectRepository.findOne({ where: { token } });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/query/entities/plugin.entity.ts
Normal file
20
src/query/entities/plugin.entity.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { Column, Entity, ManyToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
import { Query } from "./query.entity";
|
||||||
|
|
||||||
|
@Entity("plugin")
|
||||||
|
export class VmPlugin {
|
||||||
|
@PrimaryGeneratedColumn("uuid")
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 255, nullable: false })
|
||||||
|
class: string;
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 255, nullable: false })
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@ManyToMany(() => Query, (query) => query.plugins)
|
||||||
|
queries: Query[];
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 255 })
|
||||||
|
config: string;
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ import {
|
|||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
} from "typeorm";
|
} from "typeorm";
|
||||||
import { VMModule } from "./module.entity";
|
import { VMModule } from "./module.entity";
|
||||||
|
import { VmPlugin } from "./plugin.entity";
|
||||||
|
|
||||||
@Entity("query")
|
@Entity("query")
|
||||||
export class Query {
|
export class Query {
|
||||||
@ -24,4 +25,7 @@ export class Query {
|
|||||||
|
|
||||||
@ManyToMany(() => VMModule, (module) => module.queries)
|
@ManyToMany(() => VMModule, (module) => module.queries)
|
||||||
modules: VMModule[];
|
modules: VMModule[];
|
||||||
|
|
||||||
|
@ManyToMany(() => VmPlugin, (plugin) => plugin.queries)
|
||||||
|
plugins: VmPlugin[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,10 @@ export class QueryExecuterController {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Post("/run/:token")
|
@Post("/run/:token")
|
||||||
async runQuery(@Param("token") token: string, @Body() query: any) {
|
async runQuery(
|
||||||
|
@Param("token") token: string,
|
||||||
|
@Body() query: Record<string, any>
|
||||||
|
) {
|
||||||
return this.queryExecuterService.runQuery(token, query);
|
return this.queryExecuterService.runQuery(token, query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { Query } from "../entities/query.entity";
|
|||||||
import { Repository } from "typeorm";
|
import { Repository } from "typeorm";
|
||||||
import { Vm } from "../../vm/vm.class";
|
import { Vm } from "../../vm/vm.class";
|
||||||
import { VModule } from "../../vm/module.class";
|
import { VModule } from "../../vm/module.class";
|
||||||
|
import { DatabasePlugin } from "src/vm/plugins/database.plugin";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class QueryExecuterService {
|
export class QueryExecuterService {
|
||||||
@ -21,18 +22,38 @@ export class QueryExecuterService {
|
|||||||
throw new Error("Query not found");
|
throw new Error("Query not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
const vm = this.createVm(query);
|
const vm = await this.createVm(query);
|
||||||
const result = await vm.runScript(query.source);
|
const result = await vm.runScript(query.source, queryData);
|
||||||
|
|
||||||
return { message: "Query executed", result, query: queryData };
|
return { message: "Query executed", result, query: queryData };
|
||||||
}
|
}
|
||||||
|
|
||||||
private createVm(query: Query) {
|
private async createVm(query: Query) {
|
||||||
return new Vm({
|
if (query.modules === undefined) {
|
||||||
memoryLimit: 5,
|
query.modules = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.plugins === undefined) {
|
||||||
|
query.plugins = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const vm = new Vm({
|
||||||
|
memoryLimit: 128,
|
||||||
modules: query.modules.map((module) => {
|
modules: query.modules.map((module) => {
|
||||||
return new VModule(module.name, module.sourcePath);
|
return new VModule(module.name, module.sourcePath);
|
||||||
}),
|
}),
|
||||||
|
plugins: query.plugins.map((plugin) => {
|
||||||
|
switch (plugin.class) {
|
||||||
|
case "DATABASE": {
|
||||||
|
const config = JSON.parse(plugin.config);
|
||||||
|
return DatabasePlugin.init(plugin.name, config);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown plugin class: ${plugin.class}`);
|
||||||
|
}
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return await vm.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Controller, Inject } from "@nestjs/common";
|
import { Body, Controller, Inject, Post } from "@nestjs/common";
|
||||||
import { QueryHandlerService } from "./query.handler.service";
|
import { QueryHandlerService } from "./query.handler.service";
|
||||||
|
|
||||||
@Controller("query")
|
@Controller("query")
|
||||||
@ -7,4 +7,47 @@ export class QueryHandlerController {
|
|||||||
@Inject(QueryHandlerService)
|
@Inject(QueryHandlerService)
|
||||||
private readonly queryHandlerService: QueryHandlerService
|
private readonly queryHandlerService: QueryHandlerService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
@Post("create")
|
||||||
|
async createQuery(
|
||||||
|
@Body() queryData: { projectToken: string; source: string }
|
||||||
|
) {
|
||||||
|
return this.queryHandlerService.createQuery(queryData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("update/:id")
|
||||||
|
async updateQuery(
|
||||||
|
@Body() updateData: Partial<{ source: string }>,
|
||||||
|
@Inject("id") id: string
|
||||||
|
) {
|
||||||
|
return this.queryHandlerService.updateQuery(id, updateData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("module/create")
|
||||||
|
async createModule(@Body() moduleData: { name: string; sourcePath: string }) {
|
||||||
|
return this.queryHandlerService.createModule(moduleData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("plugin/create")
|
||||||
|
async createPlugin(
|
||||||
|
@Body() pluginData: { name: string; class: string; config: string }
|
||||||
|
) {
|
||||||
|
return this.queryHandlerService.createPlugin(pluginData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("module/add")
|
||||||
|
async addModuleToQuery(@Body() data: { queryId: string; moduleId: string }) {
|
||||||
|
return this.queryHandlerService.addModuleToQuery(
|
||||||
|
data.queryId,
|
||||||
|
data.moduleId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("plugin/add")
|
||||||
|
async addPluginToQuery(@Body() data: { queryId: string; pluginId: string }) {
|
||||||
|
return this.queryHandlerService.addPluginToQuery(
|
||||||
|
data.queryId,
|
||||||
|
data.pluginId
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,106 @@
|
|||||||
import { Injectable } from "@nestjs/common";
|
import { Inject, Injectable } from "@nestjs/common";
|
||||||
|
import { Repository } from "typeorm";
|
||||||
|
import { Query } from "../entities/query.entity";
|
||||||
|
import { VMModule } from "../entities/module.entity";
|
||||||
|
import { VmPlugin } from "../entities/plugin.entity";
|
||||||
|
import { InjectRepository } from "@nestjs/typeorm";
|
||||||
|
import { ProjectService } from "src/project/project.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class QueryHandlerService {}
|
export class QueryHandlerService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(Query)
|
||||||
|
private readonly queryRepository: Repository<Query>,
|
||||||
|
@InjectRepository(VMModule)
|
||||||
|
private readonly moduleRepository: Repository<VMModule>,
|
||||||
|
@InjectRepository(VmPlugin)
|
||||||
|
private readonly pluginRepository: Repository<VmPlugin>,
|
||||||
|
@Inject(ProjectService)
|
||||||
|
private readonly projectService: ProjectService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async createQuery(queryData: { projectToken: string; source: string }) {
|
||||||
|
const project = await this.projectService.findByToken(
|
||||||
|
queryData.projectToken
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!project) {
|
||||||
|
throw new Error("Project not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
queryData["project"] = project;
|
||||||
|
delete queryData.projectToken;
|
||||||
|
|
||||||
|
const query = this.queryRepository.create(queryData);
|
||||||
|
return this.queryRepository.save(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateQuery(id: string, updateData: Partial<Query>) {
|
||||||
|
const query = await this.queryRepository.findOne({ where: { id } });
|
||||||
|
|
||||||
|
if (!query) {
|
||||||
|
throw new Error("Query not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(query, updateData);
|
||||||
|
return this.queryRepository.save(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
async createModule(moduleData: { name: string; sourcePath: string }) {
|
||||||
|
const module = this.moduleRepository.create(moduleData);
|
||||||
|
return this.moduleRepository.save(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
async createPlugin(pluginData: {
|
||||||
|
name: string;
|
||||||
|
class: string;
|
||||||
|
config: string;
|
||||||
|
}) {
|
||||||
|
const plugin = this.pluginRepository.create(pluginData);
|
||||||
|
return this.pluginRepository.save(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
async addModuleToQuery(queryId: string, moduleId: string) {
|
||||||
|
const query = await this.queryRepository.findOne({
|
||||||
|
where: { id: queryId },
|
||||||
|
relations: ["modules"],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!query) {
|
||||||
|
throw new Error("Query not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
const module = await this.moduleRepository.findOne({
|
||||||
|
where: { id: moduleId },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!module) {
|
||||||
|
throw new Error("Module not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
query.modules.push(module);
|
||||||
|
return this.queryRepository.save(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
async addPluginToQuery(queryId: string, pluginId: string) {
|
||||||
|
const query = await this.queryRepository.findOne({
|
||||||
|
where: { id: queryId },
|
||||||
|
relations: ["plugins"],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!query) {
|
||||||
|
throw new Error("Query not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
const plugin = await this.pluginRepository.findOne({
|
||||||
|
where: { id: pluginId },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!plugin) {
|
||||||
|
throw new Error("Plugin not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
query.plugins.push(plugin);
|
||||||
|
return this.queryRepository.save(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Module } from "@nestjs/common";
|
import { forwardRef, Module } from "@nestjs/common";
|
||||||
import { TypeOrmModule } from "@nestjs/typeorm";
|
import { TypeOrmModule } from "@nestjs/typeorm";
|
||||||
import { Query } from "./entities/query.entity";
|
import { Query } from "./entities/query.entity";
|
||||||
import { VMModule } from "./entities/module.entity";
|
import { VMModule } from "./entities/module.entity";
|
||||||
@ -6,9 +6,14 @@ import { QueryExecuterController } from "./executer/query.executer.controller";
|
|||||||
import { QueryHandlerController } from "./handler/query.handler.controller";
|
import { QueryHandlerController } from "./handler/query.handler.controller";
|
||||||
import { QueryExecuterService } from "./executer/query.executer.service";
|
import { QueryExecuterService } from "./executer/query.executer.service";
|
||||||
import { QueryHandlerService } from "./handler/query.handler.service";
|
import { QueryHandlerService } from "./handler/query.handler.service";
|
||||||
|
import { VmPlugin } from "./entities/plugin.entity";
|
||||||
|
import { ProjectModule } from "src/project/project.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([Query, VMModule])],
|
imports: [
|
||||||
|
forwardRef(() => ProjectModule),
|
||||||
|
TypeOrmModule.forFeature([Query, VMModule, VmPlugin]),
|
||||||
|
],
|
||||||
controllers: [QueryExecuterController, QueryHandlerController],
|
controllers: [QueryExecuterController, QueryHandlerController],
|
||||||
providers: [QueryExecuterService, QueryHandlerService],
|
providers: [QueryExecuterService, QueryHandlerService],
|
||||||
})
|
})
|
||||||
|
|||||||
18
src/vm/plugin.class.ts
Normal file
18
src/vm/plugin.class.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
export abstract class Plugin {
|
||||||
|
protected name: string;
|
||||||
|
|
||||||
|
constructor(name: string) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName(): string {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static init(...args: any[]): any {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract run(...args: any[]): any;
|
||||||
|
abstract onFinish(...args: any[]): void;
|
||||||
|
}
|
||||||
5
src/vm/plugins.constants.ts
Normal file
5
src/vm/plugins.constants.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { DatabasePlugin } from "./plugins/database.plugin";
|
||||||
|
|
||||||
|
export const PluginClass = {
|
||||||
|
DATABASE: DatabasePlugin,
|
||||||
|
};
|
||||||
45
src/vm/plugins/database.plugin.ts
Normal file
45
src/vm/plugins/database.plugin.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { Plugin } from "../plugin.class";
|
||||||
|
import * as mysql from "mysql2/promise";
|
||||||
|
|
||||||
|
export class DatabasePlugin extends Plugin {
|
||||||
|
constructor(name: string, private dbConnection: any) {
|
||||||
|
if (!dbConnection || typeof dbConnection.execute !== "function") {
|
||||||
|
throw new Error(
|
||||||
|
"Invalid database connection: must be a mysql2 connection with execute method"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static init(
|
||||||
|
name: string,
|
||||||
|
config: {
|
||||||
|
host: string;
|
||||||
|
user: string;
|
||||||
|
password: string;
|
||||||
|
database: string;
|
||||||
|
}
|
||||||
|
): DatabasePlugin {
|
||||||
|
const dbConnection = mysql.createConnection({
|
||||||
|
host: config.host,
|
||||||
|
user: config.user,
|
||||||
|
password: config.password,
|
||||||
|
database: config.database,
|
||||||
|
});
|
||||||
|
|
||||||
|
return new DatabasePlugin(name, dbConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
async run(query): Promise<{
|
||||||
|
rows: any[];
|
||||||
|
fields: any[];
|
||||||
|
}> {
|
||||||
|
const [rows, fields] = await this.dbConnection.execute(query);
|
||||||
|
return { rows, fields };
|
||||||
|
}
|
||||||
|
|
||||||
|
onFinish() {
|
||||||
|
this.dbConnection.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,20 +1,28 @@
|
|||||||
import * as ivm from "isolated-vm";
|
import * as ivm from "isolated-vm";
|
||||||
import { VModule } from "./module.class";
|
import { VModule } from "./module.class";
|
||||||
|
import { Plugin } from "./plugin.class";
|
||||||
|
|
||||||
export class Vm {
|
export class Vm {
|
||||||
private memoryLimit: number;
|
private memoryLimit: number;
|
||||||
private modules: VModule[];
|
private modules: VModule[];
|
||||||
private context: any;
|
private context: any;
|
||||||
private jail: any;
|
private jail: any;
|
||||||
|
private plugins: Plugin[];
|
||||||
|
private isolate: ivm.Isolate;
|
||||||
|
|
||||||
constructor(configs: { memoryLimit: number; modules: VModule[] }) {
|
constructor(configs: {
|
||||||
|
memoryLimit: number;
|
||||||
|
modules: VModule[];
|
||||||
|
plugins: Plugin[];
|
||||||
|
}) {
|
||||||
this.memoryLimit = configs.memoryLimit;
|
this.memoryLimit = configs.memoryLimit;
|
||||||
this.modules = configs.modules;
|
this.modules = configs.modules;
|
||||||
|
this.plugins = configs.plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init(): Promise<Vm> {
|
||||||
const isolate = new ivm.Isolate({ memoryLimit: this.memoryLimit });
|
this.isolate = new ivm.Isolate({ memoryLimit: this.memoryLimit });
|
||||||
this.context = isolate.createContext();
|
this.context = await this.isolate.createContext();
|
||||||
this.jail = this.context.global;
|
this.jail = this.context.global;
|
||||||
|
|
||||||
this.jail.set("global", this.jail.derefInto());
|
this.jail.set("global", this.jail.derefInto());
|
||||||
@ -22,13 +30,22 @@ export class Vm {
|
|||||||
for (const mod of this.modules) {
|
for (const mod of this.modules) {
|
||||||
this.jail.setSync(mod.getName(), mod.getSource());
|
this.jail.setSync(mod.getName(), mod.getSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const plugin of this.plugins) {
|
||||||
|
this.jail.setSync(
|
||||||
|
plugin.getName(),
|
||||||
|
new ivm.Reference(plugin.run.bind(plugin))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setFunction(name: string, func: (...args) => any) {
|
setFunction(name: string, func: (...args) => any) {
|
||||||
this.jail.setSync(name, func);
|
this.jail.setSync(name, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
async runScript(script: string) {
|
async runScript(script: string, args: Record<string, any>): Promise<any> {
|
||||||
let resolvePromise: (value: any) => void;
|
let resolvePromise: (value: any) => void;
|
||||||
let rejectPromise: (reason?: any) => void;
|
let rejectPromise: (reason?: any) => void;
|
||||||
|
|
||||||
@ -37,11 +54,14 @@ export class Vm {
|
|||||||
rejectPromise = reject;
|
rejectPromise = reject;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setFunction("result", (...args) => {
|
this.setFunction("returnResult", (...args) => {
|
||||||
console.log("Script result:", args);
|
console.log("Script result:", args);
|
||||||
|
|
||||||
resolvePromise(args);
|
resolvePromise(args);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: log
|
||||||
|
|
||||||
this.setFunction("error", (error: any) => {
|
this.setFunction("error", (error: any) => {
|
||||||
console.error("Script error:", error);
|
console.error("Script error:", error);
|
||||||
rejectPromise(error);
|
rejectPromise(error);
|
||||||
@ -51,19 +71,25 @@ export class Vm {
|
|||||||
(async () => {
|
(async () => {
|
||||||
${script}
|
${script}
|
||||||
try {
|
try {
|
||||||
const result = await main()
|
const result = await main(${JSON.stringify(args)});
|
||||||
result(result)
|
returnResult(result)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error(e)
|
error(e)
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const compiledScript = await this.context.isolate.compileScript(
|
const compiledScript = await this.isolate.compileScript(scriptWithResult);
|
||||||
scriptWithResult
|
|
||||||
);
|
|
||||||
compiledScript.run(this.context);
|
compiledScript.run(this.context);
|
||||||
|
this.onFinish();
|
||||||
|
|
||||||
return await resultPromise;
|
return await resultPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onFinish() {
|
||||||
|
this.plugins.forEach((plugin) => {
|
||||||
|
plugin.onFinish();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
tests/base/case1.ts
Normal file
22
tests/base/case1.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import createProject from "../functions/createProject";
|
||||||
|
import createQuery from "../functions/createQuery";
|
||||||
|
import runQuery from "../functions/runQuery";
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const project = await createProject("Test Project");
|
||||||
|
|
||||||
|
const query = await createQuery(
|
||||||
|
project,
|
||||||
|
"async function main(input) { return `Hello, ${input.name}!`; }"
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(query);
|
||||||
|
|
||||||
|
const result = await runQuery(query.id, { name: "World" });
|
||||||
|
|
||||||
|
console.log("Query Result:", result);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error during test execution:", error);
|
||||||
|
}
|
||||||
|
})();
|
||||||
17
tests/functions/addModule.ts
Normal file
17
tests/functions/addModule.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default async (query: { id: string }, module: { id: string }) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(
|
||||||
|
"http://localhost:3000/query/module/add",
|
||||||
|
{
|
||||||
|
queryId: query.id,
|
||||||
|
moduleId: module.id,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in adding module to query:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
17
tests/functions/addPlugin.ts
Normal file
17
tests/functions/addPlugin.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default async (query: { id: string }, plugin: { id: string }) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(
|
||||||
|
"http://localhost:3000/query/plugin/add",
|
||||||
|
{
|
||||||
|
queryId: query.id,
|
||||||
|
pluginId: plugin.id,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in adding plugin to query:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
17
tests/functions/createModule.ts
Normal file
17
tests/functions/createModule.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default async (name: string, sourcePath: string) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(
|
||||||
|
"http://localhost:3000/query/module/create",
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
sourcePath,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in creating project or query:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
18
tests/functions/createPluign.ts
Normal file
18
tests/functions/createPluign.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default async (name: string, className: string, config: string) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(
|
||||||
|
"http://localhost:3000/query/plugin/create",
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
class: className,
|
||||||
|
config,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in creating project or query:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
16
tests/functions/createProject.ts
Normal file
16
tests/functions/createProject.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
const createProject = async (name: string) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.put("http://localhost:3000/project/create", {
|
||||||
|
name: name,
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating project:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createProject;
|
||||||
14
tests/functions/createQuery.ts
Normal file
14
tests/functions/createQuery.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default async (project: { token: string }, source: string) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post("http://localhost:3000/query/create", {
|
||||||
|
source,
|
||||||
|
projectToken: project.token,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating query:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
14
tests/functions/runQuery.ts
Normal file
14
tests/functions/runQuery.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default async (token: string, queryData: Record<string, any>) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(
|
||||||
|
`http://localhost:3000/query/run/${token}`,
|
||||||
|
queryData
|
||||||
|
);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in running query:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
14
tests/functions/updateQuery.ts
Normal file
14
tests/functions/updateQuery.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default async (query: { id: string; source: string }) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post("http://localhost:3000/query/update", {
|
||||||
|
queryId: query.id,
|
||||||
|
source: query.source,
|
||||||
|
});
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in updating query:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
132
yarn.lock
132
yarn.lock
@ -819,6 +819,11 @@ array-union@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
|
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
|
||||||
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
|
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
|
||||||
|
|
||||||
|
asynckit@^0.4.0:
|
||||||
|
version "0.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
|
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
||||||
|
|
||||||
available-typed-arrays@^1.0.7:
|
available-typed-arrays@^1.0.7:
|
||||||
version "1.0.7"
|
version "1.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
|
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
|
||||||
@ -826,6 +831,20 @@ available-typed-arrays@^1.0.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
possible-typed-array-names "^1.0.0"
|
possible-typed-array-names "^1.0.0"
|
||||||
|
|
||||||
|
aws-ssl-profiles@^1.1.1:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz#157dd77e9f19b1d123678e93f120e6f193022641"
|
||||||
|
integrity sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==
|
||||||
|
|
||||||
|
axios@^1.12.2:
|
||||||
|
version "1.12.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios/-/axios-1.12.2.tgz#6c307390136cf7a2278d09cec63b136dfc6e6da7"
|
||||||
|
integrity sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.15.6"
|
||||||
|
form-data "^4.0.4"
|
||||||
|
proxy-from-env "^1.1.0"
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||||
@ -1103,6 +1122,13 @@ color-name@~1.1.4:
|
|||||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||||
|
|
||||||
|
combined-stream@^1.0.8:
|
||||||
|
version "1.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||||
|
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||||
|
dependencies:
|
||||||
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
commander@4.1.1:
|
commander@4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
|
||||||
@ -1255,6 +1281,11 @@ define-data-property@^1.1.4:
|
|||||||
es-errors "^1.3.0"
|
es-errors "^1.3.0"
|
||||||
gopd "^1.0.1"
|
gopd "^1.0.1"
|
||||||
|
|
||||||
|
delayed-stream@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||||
|
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||||
|
|
||||||
denque@^2.1.0:
|
denque@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1"
|
resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1"
|
||||||
@ -1394,6 +1425,16 @@ es-object-atoms@^1.0.0, es-object-atoms@^1.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
es-errors "^1.3.0"
|
es-errors "^1.3.0"
|
||||||
|
|
||||||
|
es-set-tostringtag@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d"
|
||||||
|
integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==
|
||||||
|
dependencies:
|
||||||
|
es-errors "^1.3.0"
|
||||||
|
get-intrinsic "^1.2.6"
|
||||||
|
has-tostringtag "^1.0.2"
|
||||||
|
hasown "^2.0.2"
|
||||||
|
|
||||||
escalade@^3.1.1, escalade@^3.2.0:
|
escalade@^3.1.1, escalade@^3.2.0:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
|
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
|
||||||
@ -1709,6 +1750,11 @@ flatted@^3.2.9:
|
|||||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358"
|
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358"
|
||||||
integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==
|
integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==
|
||||||
|
|
||||||
|
follow-redirects@^1.15.6:
|
||||||
|
version "1.15.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340"
|
||||||
|
integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==
|
||||||
|
|
||||||
for-each@^0.3.5:
|
for-each@^0.3.5:
|
||||||
version "0.3.5"
|
version "0.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47"
|
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47"
|
||||||
@ -1742,6 +1788,17 @@ fork-ts-checker-webpack-plugin@8.0.0:
|
|||||||
semver "^7.3.5"
|
semver "^7.3.5"
|
||||||
tapable "^2.2.1"
|
tapable "^2.2.1"
|
||||||
|
|
||||||
|
form-data@^4.0.4:
|
||||||
|
version "4.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4"
|
||||||
|
integrity sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==
|
||||||
|
dependencies:
|
||||||
|
asynckit "^0.4.0"
|
||||||
|
combined-stream "^1.0.8"
|
||||||
|
es-set-tostringtag "^2.1.0"
|
||||||
|
hasown "^2.0.2"
|
||||||
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
forwarded@0.2.0:
|
forwarded@0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||||
@ -1786,12 +1843,19 @@ function-bind@^1.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||||
|
|
||||||
|
generate-function@^2.3.1:
|
||||||
|
version "2.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f"
|
||||||
|
integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==
|
||||||
|
dependencies:
|
||||||
|
is-property "^1.0.2"
|
||||||
|
|
||||||
get-caller-file@^2.0.5:
|
get-caller-file@^2.0.5:
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||||
|
|
||||||
get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.3.0:
|
get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
|
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
|
||||||
integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
|
integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
|
||||||
@ -1975,6 +2039,13 @@ iconv-lite@^0.6.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3.0.0"
|
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||||
|
|
||||||
|
iconv-lite@^0.7.0:
|
||||||
|
version "0.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.7.0.tgz#c50cd80e6746ca8115eb98743afa81aa0e147a3e"
|
||||||
|
integrity sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==
|
||||||
|
dependencies:
|
||||||
|
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||||
|
|
||||||
ieee754@^1.1.13, ieee754@^1.2.1:
|
ieee754@^1.1.13, ieee754@^1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||||
@ -2124,6 +2195,11 @@ is-path-inside@^3.0.3:
|
|||||||
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
|
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
|
||||||
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
|
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
|
||||||
|
|
||||||
|
is-property@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
|
||||||
|
integrity sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==
|
||||||
|
|
||||||
is-stream@^2.0.0:
|
is-stream@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
|
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
|
||||||
@ -2292,11 +2368,26 @@ log-symbols@^4.1.0:
|
|||||||
chalk "^4.1.0"
|
chalk "^4.1.0"
|
||||||
is-unicode-supported "^0.1.0"
|
is-unicode-supported "^0.1.0"
|
||||||
|
|
||||||
|
long@^5.2.1:
|
||||||
|
version "5.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/long/-/long-5.3.2.tgz#1d84463095999262d7d7b7f8bfd4a8cc55167f83"
|
||||||
|
integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==
|
||||||
|
|
||||||
lru-cache@^10.2.0, lru-cache@^10.4.3:
|
lru-cache@^10.2.0, lru-cache@^10.4.3:
|
||||||
version "10.4.3"
|
version "10.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
|
||||||
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
|
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
|
||||||
|
|
||||||
|
lru-cache@^7.14.1:
|
||||||
|
version "7.18.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89"
|
||||||
|
integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==
|
||||||
|
|
||||||
|
lru.min@^1.0.0:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/lru.min/-/lru.min-1.1.2.tgz#01ce1d72cc50c7faf8bd1f809ebf05d4331021eb"
|
||||||
|
integrity sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==
|
||||||
|
|
||||||
macos-release@^2.5.0:
|
macos-release@^2.5.0:
|
||||||
version "2.5.1"
|
version "2.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.5.1.tgz#bccac4a8f7b93163a8d163b8ebf385b3c5f55bf9"
|
resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.5.1.tgz#bccac4a8f7b93163a8d163b8ebf385b3c5f55bf9"
|
||||||
@ -2375,7 +2466,7 @@ mime-db@1.52.0:
|
|||||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||||
|
|
||||||
mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34:
|
mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34:
|
||||||
version "2.1.35"
|
version "2.1.35"
|
||||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||||
@ -2473,6 +2564,21 @@ mute-stream@0.0.8:
|
|||||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
|
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
|
||||||
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
|
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
|
||||||
|
|
||||||
|
mysql2@^3.15.0:
|
||||||
|
version "3.15.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-3.15.0.tgz#4cd4a13be2cc48be545b91f57a7e9b6a8c1ae925"
|
||||||
|
integrity sha512-tT6pomf5Z/I7Jzxu8sScgrYBMK9bUFWd7Kbo6Fs1L0M13OOIJ/ZobGKS3Z7tQ8Re4lj+LnLXIQVZZxa3fhYKzA==
|
||||||
|
dependencies:
|
||||||
|
aws-ssl-profiles "^1.1.1"
|
||||||
|
denque "^2.1.0"
|
||||||
|
generate-function "^2.3.1"
|
||||||
|
iconv-lite "^0.7.0"
|
||||||
|
long "^5.2.1"
|
||||||
|
lru.min "^1.0.0"
|
||||||
|
named-placeholders "^1.1.3"
|
||||||
|
seq-queue "^0.0.5"
|
||||||
|
sqlstring "^2.3.2"
|
||||||
|
|
||||||
mysql@^2.18.1:
|
mysql@^2.18.1:
|
||||||
version "2.18.1"
|
version "2.18.1"
|
||||||
resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.18.1.tgz#2254143855c5a8c73825e4522baf2ea021766717"
|
resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.18.1.tgz#2254143855c5a8c73825e4522baf2ea021766717"
|
||||||
@ -2483,6 +2589,13 @@ mysql@^2.18.1:
|
|||||||
safe-buffer "5.1.2"
|
safe-buffer "5.1.2"
|
||||||
sqlstring "2.3.1"
|
sqlstring "2.3.1"
|
||||||
|
|
||||||
|
named-placeholders@^1.1.3:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/named-placeholders/-/named-placeholders-1.1.3.tgz#df595799a36654da55dda6152ba7a137ad1d9351"
|
||||||
|
integrity sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==
|
||||||
|
dependencies:
|
||||||
|
lru-cache "^7.14.1"
|
||||||
|
|
||||||
napi-build-utils@^2.0.0:
|
napi-build-utils@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e"
|
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e"
|
||||||
@ -2774,6 +2887,11 @@ proxy-addr@~2.0.7:
|
|||||||
forwarded "0.2.0"
|
forwarded "0.2.0"
|
||||||
ipaddr.js "1.9.1"
|
ipaddr.js "1.9.1"
|
||||||
|
|
||||||
|
proxy-from-env@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||||
|
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||||
|
|
||||||
pump@^3.0.0:
|
pump@^3.0.0:
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d"
|
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d"
|
||||||
@ -3030,6 +3148,11 @@ send@0.18.0:
|
|||||||
range-parser "~1.2.1"
|
range-parser "~1.2.1"
|
||||||
statuses "2.0.1"
|
statuses "2.0.1"
|
||||||
|
|
||||||
|
seq-queue@^0.0.5:
|
||||||
|
version "0.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e"
|
||||||
|
integrity sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==
|
||||||
|
|
||||||
serialize-javascript@^6.0.2:
|
serialize-javascript@^6.0.2:
|
||||||
version "6.0.2"
|
version "6.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2"
|
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2"
|
||||||
@ -3196,6 +3319,11 @@ sqlstring@2.3.1:
|
|||||||
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40"
|
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40"
|
||||||
integrity sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==
|
integrity sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==
|
||||||
|
|
||||||
|
sqlstring@^2.3.2:
|
||||||
|
version "2.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.3.tgz#2ddc21f03bce2c387ed60680e739922c65751d0c"
|
||||||
|
integrity sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==
|
||||||
|
|
||||||
squel@^5.13.0:
|
squel@^5.13.0:
|
||||||
version "5.13.0"
|
version "5.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/squel/-/squel-5.13.0.tgz#09cc73e91f0d0e326482605ee76e3b7ac881ddf6"
|
resolved "https://registry.yarnpkg.com/squel/-/squel-5.13.0.tgz#09cc73e91f0d0e326482605ee76e3b7ac881ddf6"
|
||||||
|
|||||||
Reference in New Issue
Block a user