Convert metadata tables to camel_case (#2420)
* Convert metadata tables to camelcase * refactor folder structure * rename datasourcemetadata * regenerate metadata schema * rename dataSourceMetadata to dataSource
This commit is contained in:
66
server/src/database/commands/data-seed-tenant.command.ts
Normal file
66
server/src/database/commands/data-seed-tenant.command.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import { InjectDataSource } from '@nestjs/typeorm';
|
||||
|
||||
import { Command, CommandRunner } from 'nest-commander';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { DataSourceService } from 'src/metadata/data-source/data-source.service';
|
||||
import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service';
|
||||
import { TenantMigrationRunnerService } from 'src/tenant-migration-runner/tenant-migration-runner.service';
|
||||
import { seedCompanies } from 'src/database/typeorm-seeds/tenant/companies';
|
||||
import { seedViewFields } from 'src/database/typeorm-seeds/tenant/view-fields';
|
||||
import { seedViews } from 'src/database/typeorm-seeds/tenant/views';
|
||||
import { seedFieldMetadata } from 'src/database/typeorm-seeds/metadata/field-metadata';
|
||||
import { seedObjectMetadata } from 'src/database/typeorm-seeds/metadata/object-metadata';
|
||||
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
||||
|
||||
// TODO: implement dry-run
|
||||
@Command({
|
||||
name: 'tenant:seed',
|
||||
description:
|
||||
'Seed tenant with initial data. This command is intended for development only.',
|
||||
})
|
||||
export class DataSeedTenantCommand extends CommandRunner {
|
||||
workspaceId = 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419';
|
||||
|
||||
constructor(
|
||||
@InjectDataSource('metadata')
|
||||
private readonly metadataDataSource: DataSource,
|
||||
private readonly dataSourceService: DataSourceService,
|
||||
private readonly typeORMService: TypeORMService,
|
||||
private readonly tenantMigrationService: TenantMigrationService,
|
||||
private readonly migrationRunnerService: TenantMigrationRunnerService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
const dataSourceMetadata =
|
||||
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
|
||||
this.workspaceId,
|
||||
);
|
||||
|
||||
const workspaceDataSource = await this.typeORMService.connectToDataSource(
|
||||
dataSourceMetadata,
|
||||
);
|
||||
|
||||
if (!workspaceDataSource) {
|
||||
throw new Error('Could not connect to workspace data source');
|
||||
}
|
||||
|
||||
await seedObjectMetadata(this.metadataDataSource, 'metadata');
|
||||
await seedFieldMetadata(this.metadataDataSource, 'metadata');
|
||||
|
||||
await this.tenantMigrationService.insertStandardMigrations(
|
||||
this.workspaceId,
|
||||
);
|
||||
await this.migrationRunnerService.executeMigrationFromPendingMigrations(
|
||||
this.workspaceId,
|
||||
);
|
||||
|
||||
await seedCompanies(workspaceDataSource, dataSourceMetadata.schema);
|
||||
await seedViewFields(workspaceDataSource, dataSourceMetadata.schema);
|
||||
await seedViews(workspaceDataSource, dataSourceMetadata.schema);
|
||||
|
||||
await this.typeORMService.disconnectFromDataSource(dataSourceMetadata.id);
|
||||
}
|
||||
}
|
||||
@ -2,21 +2,36 @@ import { Module } from '@nestjs/common';
|
||||
|
||||
import { DataCleanInactiveCommand } from 'src/database/commands/clean-inactive-workspaces.command';
|
||||
import { ConfirmationQuestion } from 'src/database/commands/questions/confirmation.question';
|
||||
import { WorkspaceService } from 'src/core/workspace/services/workspace.service';
|
||||
import { PipelineModule } from 'src/core/pipeline/pipeline.module';
|
||||
import { CompanyModule } from 'src/core/company/company.module';
|
||||
import { PersonModule } from 'src/core/person/person.module';
|
||||
import { TenantInitialisationModule } from 'src/metadata/tenant-initialisation/tenant-initialisation.module';
|
||||
import { PrismaModule } from 'src/database/prisma.module';
|
||||
import { TenantManagerModule } from 'src/tenant-manager/tenant-manager.module';
|
||||
import { DataSourceModule } from 'src/metadata/data-source/data-source.module';
|
||||
import { TenantMigrationModule } from 'src/metadata/tenant-migration/tenant-migration.module';
|
||||
import { TenantMigrationRunnerModule } from 'src/tenant-migration-runner/tenant-migration-runner.module';
|
||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||
import { WorkspaceModule } from 'src/core/workspace/workspace.module';
|
||||
|
||||
import { DataSeedTenantCommand } from './data-seed-tenant.command';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
PipelineModule,
|
||||
CompanyModule,
|
||||
PersonModule,
|
||||
TenantInitialisationModule,
|
||||
TenantManagerModule,
|
||||
PrismaModule,
|
||||
DataSourceModule,
|
||||
TypeORMModule,
|
||||
TenantMigrationModule,
|
||||
TenantMigrationRunnerModule,
|
||||
WorkspaceModule,
|
||||
],
|
||||
providers: [
|
||||
DataSeedTenantCommand,
|
||||
DataCleanInactiveCommand,
|
||||
ConfirmationQuestion,
|
||||
],
|
||||
providers: [DataCleanInactiveCommand, ConfirmationQuestion, WorkspaceService],
|
||||
})
|
||||
export class DatabaseCommandModule {}
|
||||
|
||||
@ -5,8 +5,8 @@ export const seedMetadata = async (prisma: PrismaClient) => {
|
||||
'CREATE SCHEMA IF NOT EXISTS workspace_twenty_7icsva0r6s00mpcp6cwg4w4rd',
|
||||
);
|
||||
await prisma.$queryRawUnsafe(
|
||||
`INSERT INTO metadata.data_source_metadata(
|
||||
id, schema, type, workspace_id
|
||||
`INSERT INTO metadata."dataSource"(
|
||||
id, schema, type, "workspaceId"
|
||||
)
|
||||
VALUES (
|
||||
'b37b2163-7f63-47a9-b1b3-6c7290ca9fb1', 'workspace_twenty_7icsva0r6s00mpcp6cwg4w4rd', 'postgres', 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
const tableName = 'field_metadata';
|
||||
const tableName = 'fieldMetadata';
|
||||
|
||||
export const seedFieldMetadata = async (
|
||||
workspaceDataSource: DataSource,
|
||||
@ -10,7 +10,7 @@ export const seedFieldMetadata = async (
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'objectId',
|
||||
'objectMetadataId',
|
||||
'isCustom',
|
||||
'workspaceId',
|
||||
'isActive',
|
||||
@ -26,7 +26,7 @@ export const seedFieldMetadata = async (
|
||||
.values([
|
||||
// Companies
|
||||
{
|
||||
objectId: '1a8487a0-480c-434e-b4c7-e22408b97047',
|
||||
objectMetadataId: '1a8487a0-480c-434e-b4c7-e22408b97047',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -41,7 +41,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '1a8487a0-480c-434e-b4c7-e22408b97047',
|
||||
objectMetadataId: '1a8487a0-480c-434e-b4c7-e22408b97047',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -56,7 +56,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
objectId: '1a8487a0-480c-434e-b4c7-e22408b97047',
|
||||
objectMetadataId: '1a8487a0-480c-434e-b4c7-e22408b97047',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -71,7 +71,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
objectId: '1a8487a0-480c-434e-b4c7-e22408b97047',
|
||||
objectMetadataId: '1a8487a0-480c-434e-b4c7-e22408b97047',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -87,7 +87,7 @@ export const seedFieldMetadata = async (
|
||||
},
|
||||
// Views
|
||||
{
|
||||
objectId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe',
|
||||
objectMetadataId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -102,13 +102,13 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe',
|
||||
objectMetadataId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
type: 'TEXT',
|
||||
name: 'objectMetadataId',
|
||||
label: 'Object Id',
|
||||
label: 'Object Metadata Id',
|
||||
targetColumnMap: {
|
||||
value: 'objectMetadataId',
|
||||
},
|
||||
@ -117,7 +117,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe',
|
||||
objectMetadataId: '9ab6b3dc-767f-473f-8fd0-6cdbefbf8dbe',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -133,13 +133,13 @@ export const seedFieldMetadata = async (
|
||||
},
|
||||
// View Fields
|
||||
{
|
||||
objectId: '61d9000b-485c-4c48-a22e-0d9a164f9647',
|
||||
objectMetadataId: '61d9000b-485c-4c48-a22e-0d9a164f9647',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
type: 'TEXT',
|
||||
name: 'fieldMetadataId',
|
||||
label: 'Field Id',
|
||||
label: 'Field Metadata Id',
|
||||
targetColumnMap: {
|
||||
value: 'fieldMetadataId',
|
||||
},
|
||||
@ -148,7 +148,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '61d9000b-485c-4c48-a22e-0d9a164f9647',
|
||||
objectMetadataId: '61d9000b-485c-4c48-a22e-0d9a164f9647',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -163,7 +163,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '61d9000b-485c-4c48-a22e-0d9a164f9647',
|
||||
objectMetadataId: '61d9000b-485c-4c48-a22e-0d9a164f9647',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -178,7 +178,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '61d9000b-485c-4c48-a22e-0d9a164f9647',
|
||||
objectMetadataId: '61d9000b-485c-4c48-a22e-0d9a164f9647',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -193,7 +193,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '61d9000b-485c-4c48-a22e-0d9a164f9647',
|
||||
objectMetadataId: '61d9000b-485c-4c48-a22e-0d9a164f9647',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -209,13 +209,13 @@ export const seedFieldMetadata = async (
|
||||
},
|
||||
// View Filters
|
||||
{
|
||||
objectId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3',
|
||||
objectMetadataId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
type: 'TEXT',
|
||||
name: 'fieldMetadataId',
|
||||
label: 'Field Id',
|
||||
label: 'Field Metadata Id',
|
||||
targetColumnMap: {
|
||||
value: 'fieldMetadataId',
|
||||
},
|
||||
@ -224,7 +224,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3',
|
||||
objectMetadataId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -239,7 +239,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3',
|
||||
objectMetadataId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -254,7 +254,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3',
|
||||
objectMetadataId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -269,7 +269,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3',
|
||||
objectMetadataId: '5d9b1ab9-4461-4e2d-bf9e-9b47e68846d3',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -285,7 +285,7 @@ export const seedFieldMetadata = async (
|
||||
},
|
||||
// View Sorts
|
||||
{
|
||||
objectId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251',
|
||||
objectMetadataId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -300,7 +300,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251',
|
||||
objectMetadataId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
@ -315,7 +315,7 @@ export const seedFieldMetadata = async (
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
objectId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251',
|
||||
objectMetadataId: '6f8dcd4b-cf28-41dd-b98b-d6e1f5b3a251',
|
||||
isCustom: false,
|
||||
workspaceId: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419',
|
||||
isActive: true,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
const tableName = 'object_metadata';
|
||||
const tableName = 'objectMetadata';
|
||||
|
||||
export const seedObjectMetadata = async (
|
||||
workspaceDataSource: DataSource,
|
||||
|
||||
21
server/src/database/typeorm/metadata/metadata.datasource.ts
Normal file
21
server/src/database/typeorm/metadata/metadata.datasource.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
||||
|
||||
import { DataSource, DataSourceOptions } from 'typeorm';
|
||||
import { config } from 'dotenv';
|
||||
config();
|
||||
const configService = new ConfigService();
|
||||
export const typeORMMetadataModuleOptions: TypeOrmModuleOptions = {
|
||||
url: configService.get<string>('PG_DATABASE_URL'),
|
||||
type: 'postgres',
|
||||
logging: ['error'],
|
||||
schema: 'metadata',
|
||||
entities: ['dist/src/metadata/**/*.entity{.ts,.js}'],
|
||||
synchronize: false,
|
||||
migrationsRun: false,
|
||||
migrationsTableName: '_typeorm_migrations',
|
||||
migrations: [__dirname + '/migrations/*{.ts,.js}'],
|
||||
};
|
||||
export const connectionSource = new DataSource(
|
||||
typeORMMetadataModuleOptions as DataSourceOptions,
|
||||
);
|
||||
@ -0,0 +1,65 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class SetupMetadataTables1699619603804 implements MigrationInterface {
|
||||
name = 'SetupMetadataTables1699619603804';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TYPE "metadata"."dataSource_type_enum" AS ENUM('postgres')`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "metadata"."dataSource" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "url" character varying, "schema" character varying, "type" "metadata"."dataSource_type_enum" NOT NULL DEFAULT 'postgres', "label" character varying, "isRemote" boolean NOT NULL DEFAULT false, "workspaceId" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_6d01ae6c0f47baf4f8e37342268" PRIMARY KEY ("id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "metadata"."relationMetadata" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "relationType" character varying NOT NULL, "fromObjectMetadataId" uuid NOT NULL, "toObjectMetadataId" uuid NOT NULL, "fromFieldMetadataId" uuid NOT NULL, "toFieldMetadataId" uuid NOT NULL, "workspaceId" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "REL_3deb257254145a3bdde9575e7d" UNIQUE ("fromFieldMetadataId"), CONSTRAINT "REL_9dea8f90d04edbbf9c541a95c3" UNIQUE ("toFieldMetadataId"), CONSTRAINT "PK_2724f60cb4f17a89481a7e8d7d3" PRIMARY KEY ("id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "metadata"."fieldMetadata" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "objectMetadataId" uuid NOT NULL, "type" character varying NOT NULL, "name" character varying NOT NULL, "label" character varying NOT NULL, "targetColumnMap" jsonb NOT NULL, "description" text, "icon" character varying, "enums" text array, "isCustom" boolean NOT NULL DEFAULT false, "isActive" boolean NOT NULL DEFAULT false, "isNullable" boolean DEFAULT true, "workspaceId" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "IndexOnNameObjectMetadataIdAndWorkspaceIdUnique" UNIQUE ("name", "objectMetadataId", "workspaceId"), CONSTRAINT "PK_d046b1c7cea325ebc4cdc25e7a9" PRIMARY KEY ("id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "metadata"."objectMetadata" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "dataSourceId" character varying NOT NULL, "nameSingular" character varying NOT NULL, "namePlural" character varying NOT NULL, "labelSingular" character varying NOT NULL, "labelPlural" character varying NOT NULL, "description" text, "icon" character varying, "targetTableName" character varying NOT NULL, "isCustom" boolean NOT NULL DEFAULT false, "isActive" boolean NOT NULL DEFAULT false, "workspaceId" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "IndexOnNamePluralAndWorkspaceIdUnique" UNIQUE ("namePlural", "workspaceId"), CONSTRAINT "IndexOnNameSingularAndWorkspaceIdUnique" UNIQUE ("nameSingular", "workspaceId"), CONSTRAINT "PK_81fb7f4f4244211cfbd188af1e8" PRIMARY KEY ("id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "metadata"."tenantMigration" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "migrations" jsonb, "name" character varying, "isCustom" boolean NOT NULL DEFAULT false, "appliedAt" TIMESTAMP, "workspaceId" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_f9b06eb42494795f73acb5c2350" PRIMARY KEY ("id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_f2a0acd3a548ee446a1a35df44d" FOREIGN KEY ("fromObjectMetadataId") REFERENCES "metadata"."objectMetadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_0f781f589e5a527b8f3d3a4b824" FOREIGN KEY ("toObjectMetadataId") REFERENCES "metadata"."objectMetadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_3deb257254145a3bdde9575e7d6" FOREIGN KEY ("fromFieldMetadataId") REFERENCES "metadata"."fieldMetadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_9dea8f90d04edbbf9c541a95c3b" FOREIGN KEY ("toFieldMetadataId") REFERENCES "metadata"."fieldMetadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."fieldMetadata" ADD CONSTRAINT "FK_de2a09b9e3e690440480d2dee26" FOREIGN KEY ("objectMetadataId") REFERENCES "metadata"."objectMetadata"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."fieldMetadata" DROP CONSTRAINT "FK_de2a09b9e3e690440480d2dee26"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_9dea8f90d04edbbf9c541a95c3b"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_3deb257254145a3bdde9575e7d6"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_0f781f589e5a527b8f3d3a4b824"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_f2a0acd3a548ee446a1a35df44d"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "metadata"."tenantMigration"`);
|
||||
await queryRunner.query(`DROP TABLE "metadata"."objectMetadata"`);
|
||||
await queryRunner.query(`DROP TABLE "metadata"."fieldMetadata"`);
|
||||
await queryRunner.query(`DROP TABLE "metadata"."relationMetadata"`);
|
||||
await queryRunner.query(`DROP TABLE "metadata"."dataSource"`);
|
||||
await queryRunner.query(`DROP TYPE "metadata"."dataSource_type_enum"`);
|
||||
}
|
||||
}
|
||||
23
server/src/database/typeorm/typeorm.module.ts
Normal file
23
server/src/database/typeorm/typeorm.module.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
|
||||
|
||||
import { TypeORMService } from './typeorm.service';
|
||||
|
||||
import { typeORMMetadataModuleOptions } from './metadata/metadata.datasource';
|
||||
|
||||
const metadataTypeORMFactory = async (): Promise<TypeOrmModuleOptions> => ({
|
||||
...typeORMMetadataModuleOptions,
|
||||
name: 'metadata',
|
||||
});
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forRootAsync({
|
||||
useFactory: metadataTypeORMFactory,
|
||||
name: 'metadata',
|
||||
}),
|
||||
],
|
||||
providers: [TypeORMService],
|
||||
exports: [TypeORMService],
|
||||
})
|
||||
export class TypeORMModule {}
|
||||
105
server/src/database/typeorm/typeorm.service.ts
Normal file
105
server/src/database/typeorm/typeorm.service.ts
Normal file
@ -0,0 +1,105 @@
|
||||
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
|
||||
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { EnvironmentService } from 'src/integrations/environment/environment.service';
|
||||
import { DataSourceEntity } from 'src/metadata/data-source/data-source.entity';
|
||||
|
||||
@Injectable()
|
||||
export class TypeORMService implements OnModuleInit, OnModuleDestroy {
|
||||
private mainDataSource: DataSource;
|
||||
private dataSources: Map<string, DataSource> = new Map();
|
||||
|
||||
constructor(private readonly environmentService: EnvironmentService) {
|
||||
this.mainDataSource = new DataSource({
|
||||
url: environmentService.getPGDatabaseUrl(),
|
||||
type: 'postgres',
|
||||
logging: false,
|
||||
schema: 'public',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to a data source using metadata. Returns a cached connection if it exists.
|
||||
* @param dataSource DataSourceEntity
|
||||
* @returns Promise<DataSource | undefined>
|
||||
*/
|
||||
public async connectToDataSource(
|
||||
dataSource: DataSourceEntity,
|
||||
): Promise<DataSource | undefined> {
|
||||
if (this.dataSources.has(dataSource.id)) {
|
||||
return this.dataSources.get(dataSource.id);
|
||||
}
|
||||
|
||||
const schema = dataSource.schema;
|
||||
|
||||
const workspaceDataSource = new DataSource({
|
||||
url: dataSource.url ?? this.environmentService.getPGDatabaseUrl(),
|
||||
type: 'postgres',
|
||||
logging: ['query'],
|
||||
schema,
|
||||
});
|
||||
|
||||
await workspaceDataSource.initialize();
|
||||
|
||||
this.dataSources.set(dataSource.id, workspaceDataSource);
|
||||
|
||||
return workspaceDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from a workspace data source.
|
||||
* @param dataSourceId
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
public async disconnectFromDataSource(dataSourceId: string) {
|
||||
if (!this.dataSources.has(dataSourceId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dataSource = this.dataSources.get(dataSourceId);
|
||||
|
||||
await dataSource?.destroy();
|
||||
|
||||
this.dataSources.delete(dataSourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new schema
|
||||
* @param workspaceId
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
public async createSchema(schemaName: string): Promise<string> {
|
||||
const queryRunner = this.mainDataSource.createQueryRunner();
|
||||
|
||||
await queryRunner.createSchema(schemaName, true);
|
||||
|
||||
await queryRunner.release();
|
||||
|
||||
return schemaName;
|
||||
}
|
||||
|
||||
public async deleteSchema(schemaName: string) {
|
||||
const queryRunner = this.mainDataSource.createQueryRunner();
|
||||
|
||||
await queryRunner.dropSchema(schemaName, true, true);
|
||||
|
||||
await queryRunner.release();
|
||||
}
|
||||
|
||||
async onModuleInit() {
|
||||
// Init main data source "default" schema
|
||||
await this.mainDataSource.initialize();
|
||||
}
|
||||
|
||||
async onModuleDestroy() {
|
||||
// Destroy main data source "default" schema
|
||||
await this.mainDataSource.destroy();
|
||||
|
||||
// Destroy all workspace data sources
|
||||
for (const [, dataSource] of this.dataSources) {
|
||||
await dataSource.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user