feat: enhance database management with new migration and database node functionalities, including CRUD operations and test cases
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
import { Controller, Get, Inject, Post } from "@nestjs/common";
|
import { Controller, Get, Post, Body, Param } from "@nestjs/common";
|
||||||
import { DatabaseManagerService } from "./database.manager.service";
|
import { DatabaseManagerService } from "./database.manager.service";
|
||||||
import { DatabaseNodeService } from "../databaseNode/database.node.service";
|
import { DatabaseNodeService } from "../databaseNode/database.node.service";
|
||||||
import { MigrationService } from "../migration/migration.service";
|
import { MigrationService } from "../migration/migration.service";
|
||||||
@ -6,27 +6,22 @@ import { MigrationService } from "../migration/migration.service";
|
|||||||
@Controller("database")
|
@Controller("database")
|
||||||
export class DatabaseManagerController {
|
export class DatabaseManagerController {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject("DatabaseService")
|
|
||||||
private readonly databaseManagerService: DatabaseManagerService,
|
private readonly databaseManagerService: DatabaseManagerService,
|
||||||
@Inject("DatabaseNodeService")
|
|
||||||
private readonly databaseNodeService: DatabaseNodeService,
|
private readonly databaseNodeService: DatabaseNodeService,
|
||||||
@Inject("MigrationService")
|
|
||||||
private readonly migrationService: MigrationService
|
private readonly migrationService: MigrationService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Post("create")
|
@Post("create")
|
||||||
createDatabase(
|
createDatabase(@Body() body: { projectId: string; databaseNodeId: string }) {
|
||||||
@Inject("body") body: { projectId: string; databaseNodeId: string }
|
|
||||||
) {
|
|
||||||
return this.databaseManagerService.createDatabase(
|
return this.databaseManagerService.createDatabase(
|
||||||
body.projectId,
|
body.databaseNodeId,
|
||||||
body.databaseNodeId
|
body.projectId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post("node/create")
|
@Post("node/create")
|
||||||
addDatabaseNode(
|
addDatabaseNode(
|
||||||
@Inject("body")
|
@Body()
|
||||||
body: {
|
body: {
|
||||||
host: string;
|
host: string;
|
||||||
port: number;
|
port: number;
|
||||||
@ -43,18 +38,18 @@ export class DatabaseManagerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get("migration/up/:databaseId")
|
@Get("migration/up/:databaseId")
|
||||||
migrateUp(@Inject("params") params: { databaseId: string }) {
|
migrateUp(@Param("databaseId") databaseId: string) {
|
||||||
return this.migrationService.up(params.databaseId);
|
return this.migrationService.up(databaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get("migration/down/:databaseId")
|
@Get("migration/down/:databaseId")
|
||||||
migrateDown(@Inject("params") params: { databaseId: string }) {
|
migrateDown(@Param("databaseId") databaseId: string) {
|
||||||
return this.migrationService.down(params.databaseId);
|
return this.migrationService.down(databaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post("migration/create")
|
@Post("migration/create")
|
||||||
createMigration(
|
createMigration(
|
||||||
@Inject("body")
|
@Body()
|
||||||
body: {
|
body: {
|
||||||
up: string;
|
up: string;
|
||||||
down: string;
|
down: string;
|
||||||
@ -66,9 +61,9 @@ export class DatabaseManagerController {
|
|||||||
|
|
||||||
@Post("query/:databaseId")
|
@Post("query/:databaseId")
|
||||||
runQuery(
|
runQuery(
|
||||||
@Inject("params") params: { databaseId: string },
|
@Param("databaseId") databaseId: string,
|
||||||
@Inject("body") body: { query: string }
|
@Body() body: { query: string }
|
||||||
) {
|
) {
|
||||||
return this.databaseManagerService.runQuery(params.databaseId, body.query);
|
return this.databaseManagerService.runQuery(databaseId, body.query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { DatabaseNodeService } from "../databaseNode/database.node.service";
|
|||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
forwardRef(() => ProjectModule),
|
forwardRef(() => ProjectModule),
|
||||||
MigrationModule,
|
forwardRef(() => MigrationModule),
|
||||||
TypeOrmModule.forFeature([Database, DatabaseNode, Project]),
|
TypeOrmModule.forFeature([Database, DatabaseNode, Project]),
|
||||||
],
|
],
|
||||||
controllers: [DatabaseManagerController],
|
controllers: [DatabaseManagerController],
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Inject, Injectable } from "@nestjs/common";
|
import { Injectable } from "@nestjs/common";
|
||||||
import { InjectRepository } from "@nestjs/typeorm";
|
import { InjectRepository } from "@nestjs/typeorm";
|
||||||
import { Database } from "../entities/database.entity";
|
import { Database } from "../entities/database.entity";
|
||||||
import { Repository } from "typeorm";
|
import { Repository } from "typeorm";
|
||||||
@ -12,9 +12,7 @@ export class DatabaseManagerService extends DatabaseEncryptionService {
|
|||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Database)
|
@InjectRepository(Database)
|
||||||
private databaseRepository: Repository<Database>,
|
private databaseRepository: Repository<Database>,
|
||||||
@Inject(ProjectService)
|
|
||||||
private readonly projectService: ProjectService,
|
private readonly projectService: ProjectService,
|
||||||
@Inject(DatabaseNodeService)
|
|
||||||
private readonly databaseNodeService: DatabaseNodeService
|
private readonly databaseNodeService: DatabaseNodeService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
@ -24,8 +22,19 @@ export class DatabaseManagerService extends DatabaseEncryptionService {
|
|||||||
return this.databaseRepository.findOne({ where: { id } });
|
return this.databaseRepository.findOne({ where: { id } });
|
||||||
}
|
}
|
||||||
|
|
||||||
async runQuery(databaseId: string, query: string) {
|
async findByIdWithRelations(id: string): Promise<Database | null> {
|
||||||
const database = await this.findById(databaseId);
|
return this.databaseRepository.findOne({
|
||||||
|
where: { id },
|
||||||
|
relations: ["node", "project"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async runQuery(
|
||||||
|
databaseId: string,
|
||||||
|
query: string,
|
||||||
|
queryUser: boolean = false
|
||||||
|
): Promise<any> {
|
||||||
|
const database = await this.findByIdWithRelations(databaseId);
|
||||||
|
|
||||||
if (!database) {
|
if (!database) {
|
||||||
throw new Error("Database not found");
|
throw new Error("Database not found");
|
||||||
@ -34,7 +43,7 @@ export class DatabaseManagerService extends DatabaseEncryptionService {
|
|||||||
const dbConnection = await mysql.createConnection({
|
const dbConnection = await mysql.createConnection({
|
||||||
host: database.node.host,
|
host: database.node.host,
|
||||||
port: database.node.port,
|
port: database.node.port,
|
||||||
user: database.c_username,
|
user: queryUser ? database.q_username : database.c_username,
|
||||||
password: this.decryptPassword(database.password),
|
password: this.decryptPassword(database.password),
|
||||||
database: database.database,
|
database: database.database,
|
||||||
enableKeepAlive: true,
|
enableKeepAlive: true,
|
||||||
|
|||||||
@ -61,6 +61,16 @@ export class DatabaseNodeService extends DatabaseEncryptionService {
|
|||||||
username: string,
|
username: string,
|
||||||
password: string
|
password: string
|
||||||
): Promise<DatabaseNode> {
|
): Promise<DatabaseNode> {
|
||||||
|
const existingNode = await this.databaseNodeRepository.findOne({
|
||||||
|
where: { host, port },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingNode) {
|
||||||
|
existingNode.password = this.encryptPassword(password);
|
||||||
|
existingNode.username = username;
|
||||||
|
return this.databaseNodeRepository.save(existingNode);
|
||||||
|
}
|
||||||
|
|
||||||
const encryptedPassword = this.encryptPassword(password);
|
const encryptedPassword = this.encryptPassword(password);
|
||||||
const databaseNode = this.databaseNodeRepository.create({
|
const databaseNode = this.databaseNodeRepository.create({
|
||||||
host,
|
host,
|
||||||
@ -68,6 +78,7 @@ export class DatabaseNodeService extends DatabaseEncryptionService {
|
|||||||
username,
|
username,
|
||||||
password: encryptedPassword,
|
password: encryptedPassword,
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.databaseNodeRepository.save(databaseNode);
|
return this.databaseNodeRepository.save(databaseNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +92,7 @@ export class DatabaseNodeService extends DatabaseEncryptionService {
|
|||||||
return {
|
return {
|
||||||
host: node.host,
|
host: node.host,
|
||||||
port: node.port,
|
port: node.port,
|
||||||
username: node.username,
|
user: node.username,
|
||||||
password: this.decryptPassword(node.password),
|
password: this.decryptPassword(node.password),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
Column,
|
Column,
|
||||||
Entity,
|
Entity,
|
||||||
|
JoinColumn,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
OneToMany,
|
OneToMany,
|
||||||
OneToOne,
|
OneToOne,
|
||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
} from "typeorm";
|
} from "typeorm";
|
||||||
import { Migration } from "./migration.entity";
|
import { Migration } from "./migration.entity";
|
||||||
import { Project } from "src/project/entities/project.entity";
|
import { Project } from "../../project/entities/project.entity";
|
||||||
import { DatabaseNode } from "./database.node.entity";
|
import { DatabaseNode } from "./database.node.entity";
|
||||||
|
|
||||||
@Entity("database")
|
@Entity("database")
|
||||||
@ -31,6 +32,7 @@ export class Database {
|
|||||||
migrations: Migration[];
|
migrations: Migration[];
|
||||||
|
|
||||||
@OneToOne(() => Project, (project) => project.database)
|
@OneToOne(() => Project, (project) => project.database)
|
||||||
|
@JoinColumn()
|
||||||
project: Project;
|
project: Project;
|
||||||
|
|
||||||
@ManyToOne(() => DatabaseNode, (node) => node.databases)
|
@ManyToOne(() => DatabaseNode, (node) => node.databases)
|
||||||
|
|||||||
@ -1,7 +1,14 @@
|
|||||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
Index,
|
||||||
|
OneToMany,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
} from "typeorm";
|
||||||
import { Database } from "./database.entity";
|
import { Database } from "./database.entity";
|
||||||
|
|
||||||
@Entity("databaseNode")
|
@Entity("databaseNode")
|
||||||
|
@Index("IDX_DATABASE_NODE_HOST_PORT", ["host", "port"], { unique: true })
|
||||||
export class DatabaseNode {
|
export class DatabaseNode {
|
||||||
@PrimaryGeneratedColumn("uuid")
|
@PrimaryGeneratedColumn("uuid")
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@ -1,9 +1,14 @@
|
|||||||
|
import { DatabaseManagerModule } from "src/databaseManager/database/database.manager.module";
|
||||||
import { forwardRef, Module } from "@nestjs/common";
|
import { forwardRef, Module } from "@nestjs/common";
|
||||||
import { MigrationService } from "./migration.service";
|
import { MigrationService } from "./migration.service";
|
||||||
import { DatabaseModule } from "src/database/database.module";
|
import { TypeOrmModule } from "@nestjs/typeorm";
|
||||||
|
import { Migration } from "../entities/migration.entity";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [forwardRef(() => DatabaseModule)],
|
imports: [
|
||||||
|
forwardRef(() => DatabaseManagerModule),
|
||||||
|
TypeOrmModule.forFeature([Migration]),
|
||||||
|
],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
providers: [MigrationService],
|
providers: [MigrationService],
|
||||||
exports: [MigrationService],
|
exports: [MigrationService],
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Inject, Injectable } from "@nestjs/common";
|
import { Injectable, forwardRef, Inject } from "@nestjs/common";
|
||||||
import { IsNull, Not, Repository } from "typeorm";
|
import { IsNull, Not, Repository } from "typeorm";
|
||||||
import { Migration } from "../entities/migration.entity";
|
import { Migration } from "../entities/migration.entity";
|
||||||
import { InjectRepository } from "@nestjs/typeorm";
|
import { InjectRepository } from "@nestjs/typeorm";
|
||||||
@ -9,7 +9,7 @@ export class MigrationService {
|
|||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Migration)
|
@InjectRepository(Migration)
|
||||||
private readonly migrationRepository: Repository<Migration>,
|
private readonly migrationRepository: Repository<Migration>,
|
||||||
@Inject(DatabaseManagerService)
|
@Inject(forwardRef(() => DatabaseManagerService))
|
||||||
private readonly databaseService: DatabaseManagerService
|
private readonly databaseService: DatabaseManagerService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@ -1,43 +0,0 @@
|
|||||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
||||||
|
|
||||||
export class Init1758534887223 implements MigrationInterface {
|
|
||||||
name = "Init1758534887223";
|
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(
|
|
||||||
`CREATE TABLE \`token\` (\`token\` uuid NOT NULL, \`isActive\` tinyint NOT NULL DEFAULT '0', \`projectToken\` uuid NULL, PRIMARY KEY (\`token\`)) ENGINE=InnoDB`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`CREATE TABLE \`project\` (\`token\` uuid NOT NULL, \`name\` varchar(255) NOT NULL, PRIMARY KEY (\`token\`)) ENGINE=InnoDB`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`CREATE TABLE \`module\` (\`id\` uuid NOT NULL, \`sourcePath\` varchar(255) NOT NULL, \`name\` varchar(255) NOT NULL, \`isInjectable\` tinyint NOT NULL DEFAULT '1', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`CREATE TABLE \`query\` (\`id\` uuid NOT NULL, \`source\` longtext NOT NULL, \`isActive\` tinyint NOT NULL DEFAULT '1', \`projectToken\` uuid NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`CREATE TABLE \`plugin\` (\`id\` uuid NOT NULL, \`class\` varchar(255) NOT NULL, \`name\` varchar(255) NOT NULL, \`config\` varchar(255) NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`token\` ADD CONSTRAINT \`FK_f0bc174c878df5e005c38fe05bd\` FOREIGN KEY (\`projectToken\`) REFERENCES \`project\`(\`token\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`query\` ADD CONSTRAINT \`FK_f58429a7d32fbb51ead8c4daf0a\` FOREIGN KEY (\`projectToken\`) REFERENCES \`project\`(\`token\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`query\` DROP FOREIGN KEY \`FK_f58429a7d32fbb51ead8c4daf0a\``
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`token\` DROP FOREIGN KEY \`FK_f0bc174c878df5e005c38fe05bd\``
|
|
||||||
);
|
|
||||||
await queryRunner.query(`DROP TABLE \`plugin\``);
|
|
||||||
await queryRunner.query(`DROP TABLE \`query\``);
|
|
||||||
await queryRunner.query(`DROP TABLE \`module\``);
|
|
||||||
await queryRunner.query(`DROP TABLE \`project\``);
|
|
||||||
await queryRunner.query(`DROP TABLE \`token\``);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
||||||
|
|
||||||
export class Defaults1758550333691 implements MigrationInterface {
|
|
||||||
name = 'Defaults1758550333691'
|
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(`ALTER TABLE \`module\` DROP COLUMN \`isInjectable\``);
|
|
||||||
await queryRunner.query(`ALTER TABLE \`plugin\` ADD \`queryId\` uuid NULL`);
|
|
||||||
await queryRunner.query(`ALTER TABLE \`plugin\` ADD CONSTRAINT \`FK_5162d18c3653d35ff4d104dd940\` FOREIGN KEY (\`queryId\`) REFERENCES \`query\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(`ALTER TABLE \`plugin\` DROP FOREIGN KEY \`FK_5162d18c3653d35ff4d104dd940\``);
|
|
||||||
await queryRunner.query(`ALTER TABLE \`plugin\` DROP COLUMN \`queryId\``);
|
|
||||||
await queryRunner.query(`ALTER TABLE \`module\` ADD \`isInjectable\` tinyint NOT NULL DEFAULT 1`);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
||||||
|
|
||||||
export class QueryModulesJoin1758551707113 implements MigrationInterface {
|
|
||||||
name = 'QueryModulesJoin1758551707113'
|
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(`CREATE TABLE \`query_modules_module\` (\`queryId\` uuid NOT NULL, \`moduleId\` uuid NOT NULL, INDEX \`IDX_12121324c524e12538de4948ce\` (\`queryId\`), INDEX \`IDX_7fb42dbc85874aafbd4bfb1c10\` (\`moduleId\`), PRIMARY KEY (\`queryId\`, \`moduleId\`)) ENGINE=InnoDB`);
|
|
||||||
await queryRunner.query(`ALTER TABLE \`query_modules_module\` ADD CONSTRAINT \`FK_12121324c524e12538de4948cee\` FOREIGN KEY (\`queryId\`) REFERENCES \`query\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`);
|
|
||||||
await queryRunner.query(`ALTER TABLE \`query_modules_module\` ADD CONSTRAINT \`FK_7fb42dbc85874aafbd4bfb1c101\` FOREIGN KEY (\`moduleId\`) REFERENCES \`module\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(`ALTER TABLE \`query_modules_module\` DROP FOREIGN KEY \`FK_7fb42dbc85874aafbd4bfb1c101\``);
|
|
||||||
await queryRunner.query(`ALTER TABLE \`query_modules_module\` DROP FOREIGN KEY \`FK_12121324c524e12538de4948cee\``);
|
|
||||||
await queryRunner.query(`DROP INDEX \`IDX_7fb42dbc85874aafbd4bfb1c10\` ON \`query_modules_module\``);
|
|
||||||
await queryRunner.query(`DROP INDEX \`IDX_12121324c524e12538de4948ce\` ON \`query_modules_module\``);
|
|
||||||
await queryRunner.query(`DROP TABLE \`query_modules_module\``);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
||||||
|
|
||||||
export class Migrations1758912793124 implements MigrationInterface {
|
|
||||||
name = "Migrations1758912793124";
|
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(
|
|
||||||
`CREATE TABLE \`migration\` (\`id\` varchar(36) NOT NULL, \`name\` varchar(255) NOT NULL, \`appliedAt\` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP(), \`isApplied\` tinyint NOT NULL DEFAULT '1', \`isValid\` tinyint NOT NULL DEFAULT '1', \`sql\` varchar(255) NOT NULL, \`data\` json NULL, \`projectToken\` varchar(36) NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`CREATE TABLE \`query_modules_module\` (\`queryId\` varchar(36) NOT NULL, \`moduleId\` varchar(36) NOT NULL, INDEX \`IDX_12121324c524e12538de4948ce\` (\`queryId\`), INDEX \`IDX_7fb42dbc85874aafbd4bfb1c10\` (\`moduleId\`), PRIMARY KEY (\`queryId\`, \`moduleId\`)) ENGINE=InnoDB`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`module\` DROP COLUMN \`isInjectable\``
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`plugin\` ADD \`queryId\` varchar(36) NULL`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`migration\` ADD CONSTRAINT \`FK_d3d093f32ce7c968b02fc6bce65\` FOREIGN KEY (\`projectToken\`) REFERENCES \`project\`(\`token\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`plugin\` ADD CONSTRAINT \`FK_5162d18c3653d35ff4d104dd940\` FOREIGN KEY (\`queryId\`) REFERENCES \`query\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`query_modules_module\` ADD CONSTRAINT \`FK_12121324c524e12538de4948cee\` FOREIGN KEY (\`queryId\`) REFERENCES \`query\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`query_modules_module\` ADD CONSTRAINT \`FK_7fb42dbc85874aafbd4bfb1c101\` FOREIGN KEY (\`moduleId\`) REFERENCES \`module\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`query_modules_module\` DROP FOREIGN KEY \`FK_7fb42dbc85874aafbd4bfb1c101\``
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`query_modules_module\` DROP FOREIGN KEY \`FK_12121324c524e12538de4948cee\``
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`plugin\` DROP FOREIGN KEY \`FK_5162d18c3653d35ff4d104dd940\``
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`migration\` DROP FOREIGN KEY \`FK_d3d093f32ce7c968b02fc6bce65\``
|
|
||||||
);
|
|
||||||
await queryRunner.query(`ALTER TABLE \`plugin\` DROP COLUMN \`queryId\``);
|
|
||||||
await queryRunner.query(
|
|
||||||
`ALTER TABLE \`module\` ADD \`isInjectable\` tinyint NOT NULL DEFAULT 1`
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`DROP INDEX \`IDX_7fb42dbc85874aafbd4bfb1c10\` ON \`query_modules_module\``
|
|
||||||
);
|
|
||||||
await queryRunner.query(
|
|
||||||
`DROP INDEX \`IDX_12121324c524e12538de4948ce\` ON \`query_modules_module\``
|
|
||||||
);
|
|
||||||
await queryRunner.query(`DROP TABLE \`query_modules_module\``);
|
|
||||||
await queryRunner.query(`DROP TABLE \`migration\``);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
98
src/migrations/1759002866941-init.ts
Normal file
98
src/migrations/1759002866941-init.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class Init1759002866941 implements MigrationInterface {
|
||||||
|
name = "Init1759002866941";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE \`token\` (\`token\` varchar(36) NOT NULL, \`isActive\` tinyint NOT NULL DEFAULT '0', \`projectId\` varchar(36) NULL, PRIMARY KEY (\`token\`)) ENGINE=InnoDB`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE \`migration\` (\`id\` varchar(36) NOT NULL, \`appliedAt\` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP(), \`isApplied\` tinyint NOT NULL DEFAULT '1', \`isValid\` tinyint NOT NULL DEFAULT '1', \`up\` longtext NOT NULL, \`down\` longtext NOT NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`databaseId\` varchar(36) NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE \`databaseNode\` (\`id\` varchar(36) NOT NULL, \`host\` varchar(255) NOT NULL, \`port\` int NOT NULL, \`username\` varchar(255) NOT NULL, \`password\` varchar(255) NOT NULL, UNIQUE INDEX \`IDX_DATABASE_NODE_HOST_PORT\` (\`host\`, \`port\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE \`database\` (\`id\` varchar(36) NOT NULL, \`q_username\` varchar(255) NOT NULL, \`c_username\` varchar(255) NOT NULL, \`password\` varchar(255) NOT NULL, \`database\` varchar(255) NOT NULL, \`nodeId\` varchar(36) NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE \`project\` (\`id\` varchar(36) NOT NULL, \`name\` varchar(255) NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE \`module\` (\`id\` varchar(36) NOT NULL, \`sourcePath\` varchar(255) NOT NULL, \`name\` varchar(255) NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
||||||
|
);
|
||||||
|
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, \`queryId\` varchar(36) NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE \`query\` (\`id\` varchar(36) NOT NULL, \`source\` longtext NOT NULL, \`isActive\` tinyint NOT NULL DEFAULT '1', \`projectId\` varchar(36) NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE \`query_modules_module\` (\`queryId\` varchar(36) NOT NULL, \`moduleId\` varchar(36) NOT NULL, INDEX \`IDX_12121324c524e12538de4948ce\` (\`queryId\`), INDEX \`IDX_7fb42dbc85874aafbd4bfb1c10\` (\`moduleId\`), PRIMARY KEY (\`queryId\`, \`moduleId\`)) ENGINE=InnoDB`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`token\` ADD CONSTRAINT \`FK_1e287222c887ffb2c3302880588\` FOREIGN KEY (\`projectId\`) REFERENCES \`project\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`migration\` ADD CONSTRAINT \`FK_72832cfef0fdac2f4a0e017a6b8\` FOREIGN KEY (\`databaseId\`) REFERENCES \`database\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`database\` ADD CONSTRAINT \`FK_d668eb5daf53aa3eb388953db08\` FOREIGN KEY (\`nodeId\`) REFERENCES \`databaseNode\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`plugin\` ADD CONSTRAINT \`FK_5162d18c3653d35ff4d104dd940\` FOREIGN KEY (\`queryId\`) REFERENCES \`query\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`query\` ADD CONSTRAINT \`FK_a8e4452beec9f0228fb45de99fe\` FOREIGN KEY (\`projectId\`) REFERENCES \`project\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`query_modules_module\` ADD CONSTRAINT \`FK_12121324c524e12538de4948cee\` FOREIGN KEY (\`queryId\`) REFERENCES \`query\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`query_modules_module\` ADD CONSTRAINT \`FK_7fb42dbc85874aafbd4bfb1c101\` FOREIGN KEY (\`moduleId\`) REFERENCES \`module\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`query_modules_module\` DROP FOREIGN KEY \`FK_7fb42dbc85874aafbd4bfb1c101\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`query_modules_module\` DROP FOREIGN KEY \`FK_12121324c524e12538de4948cee\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`query\` DROP FOREIGN KEY \`FK_a8e4452beec9f0228fb45de99fe\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`plugin\` DROP FOREIGN KEY \`FK_5162d18c3653d35ff4d104dd940\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`database\` DROP FOREIGN KEY \`FK_d668eb5daf53aa3eb388953db08\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`migration\` DROP FOREIGN KEY \`FK_72832cfef0fdac2f4a0e017a6b8\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`token\` DROP FOREIGN KEY \`FK_1e287222c887ffb2c3302880588\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP INDEX \`IDX_7fb42dbc85874aafbd4bfb1c10\` ON \`query_modules_module\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP INDEX \`IDX_12121324c524e12538de4948ce\` ON \`query_modules_module\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE \`query_modules_module\``);
|
||||||
|
await queryRunner.query(`DROP TABLE \`query\``);
|
||||||
|
await queryRunner.query(`DROP TABLE \`plugin\``);
|
||||||
|
await queryRunner.query(`DROP TABLE \`module\``);
|
||||||
|
await queryRunner.query(`DROP TABLE \`project\``);
|
||||||
|
await queryRunner.query(`DROP TABLE \`database\``);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP INDEX \`IDX_DATABASE_NODE_HOST_PORT\` ON \`databaseNode\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE \`databaseNode\``);
|
||||||
|
await queryRunner.query(`DROP TABLE \`migration\``);
|
||||||
|
await queryRunner.query(`DROP TABLE \`token\``);
|
||||||
|
}
|
||||||
|
}
|
||||||
59
src/migrations/1759005139426-fix.ts
Normal file
59
src/migrations/1759005139426-fix.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class Fix1759005139426 implements MigrationInterface {
|
||||||
|
name = "Fix1759005139426";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`database\` ADD \`projectId\` varchar(36) NULL`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`database\` ADD UNIQUE INDEX \`IDX_3b4af405edcc8df2198286c89d\` (\`projectId\`)`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`project\` ADD \`databaseId\` varchar(36) NULL`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`project\` ADD UNIQUE INDEX \`IDX_6212e562f65574a73b47251265\` (\`databaseId\`)`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE UNIQUE INDEX \`REL_3b4af405edcc8df2198286c89d\` ON \`database\` (\`projectId\`)`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE UNIQUE INDEX \`REL_6212e562f65574a73b47251265\` ON \`project\` (\`databaseId\`)`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`database\` ADD CONSTRAINT \`FK_3b4af405edcc8df2198286c89d2\` FOREIGN KEY (\`projectId\`) REFERENCES \`project\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`project\` ADD CONSTRAINT \`FK_6212e562f65574a73b47251265b\` FOREIGN KEY (\`databaseId\`) REFERENCES \`database\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`project\` DROP FOREIGN KEY \`FK_6212e562f65574a73b47251265b\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`database\` DROP FOREIGN KEY \`FK_3b4af405edcc8df2198286c89d2\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP INDEX \`REL_6212e562f65574a73b47251265\` ON \`project\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP INDEX \`REL_3b4af405edcc8df2198286c89d\` ON \`database\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`project\` DROP INDEX \`IDX_6212e562f65574a73b47251265\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`project\` DROP COLUMN \`databaseId\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`database\` DROP INDEX \`IDX_3b4af405edcc8df2198286c89d\``
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`database\` DROP COLUMN \`projectId\``
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,11 +3,12 @@ import { Query } from "../../query/entities/query.entity";
|
|||||||
import {
|
import {
|
||||||
Column,
|
Column,
|
||||||
Entity,
|
Entity,
|
||||||
|
JoinColumn,
|
||||||
OneToMany,
|
OneToMany,
|
||||||
OneToOne,
|
OneToOne,
|
||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
} from "typeorm";
|
} from "typeorm";
|
||||||
import { Database } from "src/databaseManager/entities/database.entity";
|
import { Database } from "../../databaseManager/entities/database.entity";
|
||||||
|
|
||||||
@Entity("project")
|
@Entity("project")
|
||||||
export class Project {
|
export class Project {
|
||||||
@ -21,6 +22,7 @@ export class Project {
|
|||||||
apiTokens: Token[];
|
apiTokens: Token[];
|
||||||
|
|
||||||
@OneToOne(() => Database, (database) => database.project)
|
@OneToOne(() => Database, (database) => database.project)
|
||||||
|
@JoinColumn()
|
||||||
database: Database;
|
database: Database;
|
||||||
|
|
||||||
@OneToMany(() => Query, (query) => query.project)
|
@OneToMany(() => Query, (query) => query.project)
|
||||||
|
|||||||
16
tests/base/createDbNode.ts
Normal file
16
tests/base/createDbNode.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import createDatabaseNode from "../functions/createDatabaseNode";
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const node = await createDatabaseNode(
|
||||||
|
"localhost",
|
||||||
|
3306,
|
||||||
|
"root",
|
||||||
|
"password"
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("node", node);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error during test execution:", error);
|
||||||
|
}
|
||||||
|
})();
|
||||||
@ -1,21 +1,42 @@
|
|||||||
|
import createDatabase from "../functions/createDatabase";
|
||||||
|
import createDatabaseNode from "../functions/createDatabaseNode";
|
||||||
import createMigration from "../functions/createMigration";
|
import createMigration from "../functions/createMigration";
|
||||||
import createProject from "../functions/createProject";
|
import createProject from "../functions/createProject";
|
||||||
|
import databaseMigrationUp from "..//functions/databaseMigrationUp";
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const project = await createProject("Test Project");
|
const node = await createDatabaseNode("localhost", 3306, "root", "root");
|
||||||
|
|
||||||
const result_1 = await createMigration(project.token, [
|
console.log("Database node created:", node);
|
||||||
{
|
|
||||||
name: "users",
|
|
||||||
fields: {
|
|
||||||
name: { type: "string", isNullable: false },
|
|
||||||
age: { type: "int", isNullable: true },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
console.log("Migration 1:", result_1.data);
|
const project = await createProject("Test Migrations Project");
|
||||||
|
|
||||||
|
console.log("Project created:", project);
|
||||||
|
|
||||||
|
const db = await createDatabase(project.id, node.id);
|
||||||
|
|
||||||
|
console.log("Database created:", db);
|
||||||
|
|
||||||
|
const migration = await createMigration(
|
||||||
|
db.id,
|
||||||
|
"CREATE TABLE `test` (id INT)",
|
||||||
|
"DROP TABLE `test`"
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("Migration created:", migration);
|
||||||
|
|
||||||
|
const migration2 = await createMigration(
|
||||||
|
db.id,
|
||||||
|
"ALTER TABLE `test` ADD COLUMN name VARCHAR(255)",
|
||||||
|
"ALTER TABLE `test` DROP COLUMN name"
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("Second Migration created:", migration2);
|
||||||
|
|
||||||
|
const migrationsUp = await databaseMigrationUp(db.id);
|
||||||
|
|
||||||
|
console.log("Migrations applied:", migrationsUp);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error during test execution:", error);
|
console.error("Error during test execution:", error);
|
||||||
}
|
}
|
||||||
|
|||||||
15
tests/functions/createDatabase.ts
Normal file
15
tests/functions/createDatabase.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import { config } from "../config";
|
||||||
|
|
||||||
|
export default async (projectId: string, databaseNodeId: string) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`${config.url}/database/create`, {
|
||||||
|
projectId,
|
||||||
|
databaseNodeId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in creating database:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
22
tests/functions/createDatabaseNode.ts
Normal file
22
tests/functions/createDatabaseNode.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { config } from "../config";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default async (
|
||||||
|
host: string,
|
||||||
|
port: number,
|
||||||
|
username: string,
|
||||||
|
password: string
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`${config.url}/database/node/create`, {
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in creating database node:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,12 +1,20 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { config } from "../config";
|
import { config } from "../config";
|
||||||
|
|
||||||
export default async (token: string, tables: any) => {
|
export default async (
|
||||||
|
databaseId: string,
|
||||||
|
upQuery: string,
|
||||||
|
downQuery: string
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`${config.url}/migrations/create`, {
|
const response = await axios.post(
|
||||||
token,
|
`${config.url}/database/migration/create`,
|
||||||
tables,
|
{
|
||||||
});
|
databaseId,
|
||||||
|
up: upQuery,
|
||||||
|
down: downQuery,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
14
tests/functions/databaseMigrationUp.ts
Normal file
14
tests/functions/databaseMigrationUp.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { config } from "../config";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default async (databaseId: string) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(
|
||||||
|
`${config.url}/database/migration/up/${databaseId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in migrating database up:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user