Sync metadata generate migrations (#2864)

* Sync Metadata generates migrations

* add execute migrations

* fix relations + add isActive on creation

* fix composite fields migration

* remove dependency

* use new metadata setup for seed-dev

* fix rebase

* remove unused code

* fix viewField dev seeds

* fix isSystem
This commit is contained in:
Weiko
2023-12-07 19:22:34 +01:00
committed by GitHub
parent 590912b30f
commit 5efc2f00b9
66 changed files with 2393 additions and 2943 deletions
@@ -2,19 +2,18 @@ import { Command, CommandRunner } from 'nest-commander';
import { DataSource } from 'typeorm';
import { DataSourceService } from 'src/metadata/data-source/data-source.service';
import { WorkspaceMigrationService } from 'src/metadata/workspace-migration/workspace-migration.service';
import { WorkspaceMigrationRunnerService } from 'src/workspace/workspace-migration-runner/workspace-migration-runner.service';
import { seedCompanies } from 'src/database/typeorm-seeds/workspace/companies';
import { seedViewFields } from 'src/database/typeorm-seeds/workspace/view-fields';
import { seedViews } from 'src/database/typeorm-seeds/workspace/views';
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
import { seedMetadataSchema } from 'src/database/typeorm-seeds/metadata';
import { seedOpportunity } from 'src/database/typeorm-seeds/workspace/opportunity';
import { seedPipelineStep } from 'src/database/typeorm-seeds/workspace/pipeline-step';
import { seedWorkspaceMember } from 'src/database/typeorm-seeds/workspace/workspaceMember';
import { seedPeople } from 'src/database/typeorm-seeds/workspace/people';
import { seedCoreSchema } from 'src/database/typeorm-seeds/core';
import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { WorkspaceSyncMetadataService } from 'src/workspace/workspace-sync-metadata/workspace-sync.metadata.service';
import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service';
import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service';
// TODO: implement dry-run
@Command({
@@ -29,8 +28,9 @@ export class DataSeedWorkspaceCommand extends CommandRunner {
private readonly environmentService: EnvironmentService,
private readonly dataSourceService: DataSourceService,
private readonly typeORMService: TypeORMService,
private readonly workspaceMigrationService: WorkspaceMigrationService,
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
private readonly workspaceSyncMetadataService: WorkspaceSyncMetadataService,
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
private readonly objectMetadataService: ObjectMetadataService,
) {
super();
}
@@ -41,13 +41,30 @@ export class DataSeedWorkspaceCommand extends CommandRunner {
url: this.environmentService.getPGDatabaseUrl(),
type: 'postgres',
logging: true,
schema: 'public',
schema: 'core',
});
await dataSource.initialize();
await seedCoreSchema(dataSource, this.workspaceId);
await seedMetadataSchema(dataSource);
await dataSource.destroy();
const schemaName = await this.workspaceDataSourceService.createWorkspaceDBSchema(
this.workspaceId,
);
const dataSourceMetadata =
await this.dataSourceService.createDataSourceMetadata(
this.workspaceId,
schemaName,
);
await this.workspaceSyncMetadataService.syncStandardObjectsAndFieldsMetadata(
dataSourceMetadata.id,
this.workspaceId,
);
} catch (error) {
console.error(error);
@@ -68,20 +85,27 @@ export class DataSeedWorkspaceCommand extends CommandRunner {
}
try {
await this.workspaceMigrationService.insertStandardMigrations(
this.workspaceId,
);
await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations(
this.workspaceId,
);
const objectMetadata = await this.objectMetadataService.findManyWithinWorkspace(this.workspaceId);
const objectMetadataMap = objectMetadata.reduce((acc, object) => {
acc[object.nameSingular] = {
id: object.id,
fields: object.fields.reduce((acc, field) => {
acc[field.name] = field.id;
return acc;
}, {}),
};
return acc;
}, {});
await seedCompanies(workspaceDataSource, dataSourceMetadata.schema);
await seedPeople(workspaceDataSource, dataSourceMetadata.schema);
await seedPipelineStep(workspaceDataSource, dataSourceMetadata.schema);
await seedOpportunity(workspaceDataSource, dataSourceMetadata.schema);
await seedViews(workspaceDataSource, dataSourceMetadata.schema);
await seedViewFields(workspaceDataSource, dataSourceMetadata.schema);
await seedViews(workspaceDataSource, dataSourceMetadata.schema, objectMetadataMap);
await seedWorkspaceMember(workspaceDataSource, dataSourceMetadata.schema);
} catch (error) {
console.error(error);
@@ -9,15 +9,19 @@ import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
import { WorkspaceModule } from 'src/core/workspace/workspace.module';
import { DataSeedWorkspaceCommand } from 'src/database/commands/data-seed-dev-workspace.command';
import { DataSeedDemoWorkspaceCommand } from 'src/database/commands/data-seed-demo-workspace.command';
import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module';
import { WorkspaceSyncMetadataModule } from 'src/workspace/workspace-sync-metadata/worksapce-sync-metadata.module';
import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module';
@Module({
imports: [
WorkspaceManagerModule,
DataSourceModule,
TypeORMModule,
WorkspaceMigrationModule,
WorkspaceMigrationRunnerModule,
WorkspaceModule,
WorkspaceDataSourceModule,
WorkspaceSyncMetadataModule,
ObjectMetadataModule,
],
providers: [
DataSeedWorkspaceCommand,
@@ -124,19 +124,19 @@ export const seedViewFilterFieldMetadata = async (
isCustom: false,
workspaceId: SeedWorkspaceId,
isActive: true,
type: FieldMetadataType.UUID,
name: 'viewId',
label: 'View Id',
type: FieldMetadataType.RELATION,
name: 'view',
label: 'View',
targetColumnMap: {},
description: 'View Filter related view',
icon: 'IconLayoutCollage',
isNullable: false,
isNullable: true,
isSystem: false,
defaultValue: undefined,
},
{
id: SeedViewFilterFieldMetadataIds.ViewForeignKey,
objectMetadataId: SeedObjectMetadataIds.ViewField,
objectMetadataId: SeedObjectMetadataIds.ViewFilter,
isCustom: false,
workspaceId: SeedWorkspaceId,
isActive: true,
@@ -1,169 +0,0 @@
import { DataSource } from 'typeorm';
import { SeedViewIds } from 'src/database/typeorm-seeds/workspace/views';
import { SeedCompanyFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/company';
import { SeedPersonFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/person';
import { SeedOpportunityFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/opportunity';
const tableName = 'viewField';
export const seedViewFields = async (
workspaceDataSource: DataSource,
schemaName: string,
) => {
await workspaceDataSource
.createQueryBuilder()
.insert()
.into(`${schemaName}.${tableName}`, [
'fieldMetadataId',
'viewId',
'position',
'isVisible',
'size',
])
.orIgnore()
.values([
{
fieldMetadataId: SeedCompanyFieldMetadataIds.Name,
viewId: SeedViewIds.Company,
position: 0,
isVisible: true,
size: 180,
},
{
fieldMetadataId: SeedCompanyFieldMetadataIds.DomainName,
viewId: SeedViewIds.Company,
position: 1,
isVisible: true,
size: 100,
},
{
fieldMetadataId: SeedCompanyFieldMetadataIds.AccountOwner,
viewId: SeedViewIds.Company,
position: 2,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedCompanyFieldMetadataIds.CreatedAt,
viewId: SeedViewIds.Company,
position: 3,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedCompanyFieldMetadataIds.Employees,
viewId: SeedViewIds.Company,
position: 4,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedCompanyFieldMetadataIds.LinkedinLink,
viewId: SeedViewIds.Company,
position: 5,
isVisible: true,
size: 170,
},
{
fieldMetadataId: SeedCompanyFieldMetadataIds.Address,
viewId: SeedViewIds.Company,
position: 6,
isVisible: true,
size: 170,
},
{
fieldMetadataId: SeedPersonFieldMetadataIds.Name,
viewId: SeedViewIds.Person,
position: 0,
isVisible: true,
size: 210,
},
{
fieldMetadataId: SeedPersonFieldMetadataIds.Email,
viewId: SeedViewIds.Person,
position: 1,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedPersonFieldMetadataIds.Company,
viewId: SeedViewIds.Person,
position: 2,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedPersonFieldMetadataIds.Phone,
viewId: SeedViewIds.Person,
position: 3,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedPersonFieldMetadataIds.CreatedAt,
viewId: SeedViewIds.Person,
position: 4,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedPersonFieldMetadataIds.City,
viewId: SeedViewIds.Person,
position: 5,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedPersonFieldMetadataIds.JobTitle,
viewId: SeedViewIds.Person,
position: 6,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedPersonFieldMetadataIds.LinkedinLink,
viewId: SeedViewIds.Person,
position: 7,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedPersonFieldMetadataIds.XLink,
viewId: SeedViewIds.Person,
position: 8,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedOpportunityFieldMetadataIds.Amount,
viewId: SeedViewIds.Opportunity,
position: 0,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedOpportunityFieldMetadataIds.CloseDate,
viewId: SeedViewIds.Opportunity,
position: 1,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedOpportunityFieldMetadataIds.Probability,
viewId: SeedViewIds.Opportunity,
position: 2,
isVisible: true,
size: 150,
},
{
fieldMetadataId: SeedOpportunityFieldMetadataIds.PointOfContact,
viewId: SeedViewIds.Opportunity,
position: 3,
isVisible: true,
size: 150,
},
])
.execute();
};
@@ -1,48 +1,198 @@
import { DataSource } from 'typeorm';
import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/object-metadata';
const tableName = 'view';
export const enum SeedViewIds {
Company = '20202020-2441-4424-8163-4002c523d415',
Person = '20202020-1979-447d-8115-593744eb4ead',
Opportunity = '20202020-b2b3-48a5-96ce-0936d6af21f7',
}
import { ObjectMetadataEntity } from 'src/metadata/object-metadata/object-metadata.entity';
export const seedViews = async (
workspaceDataSource: DataSource,
schemaName: string,
objectMetadataMap: Record<string, ObjectMetadataEntity>,
) => {
const createdViews = await workspaceDataSource
.createQueryBuilder()
.insert()
.into(`${schemaName}.view`, [
'name',
'objectMetadataId',
'type',
])
.values([
{
name: 'All Companies',
objectMetadataId: objectMetadataMap['company'].id,
type: 'table',
},
{
name: 'All People',
objectMetadataId: objectMetadataMap['person'].id,
type: 'table',
},
{
name: 'All Opportunities',
objectMetadataId: objectMetadataMap['opportunity'].id,
type: 'kanban',
},
])
.returning('*')
.execute();
const viewIdMap = createdViews.raw.reduce((acc, view) => {
acc[view.name] = view.id;
return acc;
}, {});
await workspaceDataSource
.createQueryBuilder()
.insert()
.into(`${schemaName}.${tableName}`, [
'id',
'name',
'objectMetadataId',
'type',
])
.orIgnore()
.values([
{
id: SeedViewIds.Company,
name: 'All Companies',
objectMetadataId: SeedObjectMetadataIds.Company,
type: 'table',
},
{
id: SeedViewIds.Person,
name: 'All People',
objectMetadataId: SeedObjectMetadataIds.Person,
type: 'table',
},
{
id: SeedViewIds.Opportunity,
name: 'All Opportunities',
objectMetadataId: SeedObjectMetadataIds.Opportunity,
type: 'kanban',
},
])
.execute();
.createQueryBuilder()
.insert()
.into(`${schemaName}.viewField`, [
'fieldMetadataId',
'viewId',
'position',
'isVisible',
'size',
])
.values([
{
fieldMetadataId: objectMetadataMap['company'].fields['name'],
viewId: viewIdMap['All Companies'],
position: 0,
isVisible: true,
size: 180,
},
{
fieldMetadataId: objectMetadataMap['company'].fields['domainName'],
viewId: viewIdMap['All Companies'],
position: 1,
isVisible: true,
size: 100,
},
{
fieldMetadataId: objectMetadataMap['company'].fields['accountOwner'],
viewId: viewIdMap['All Companies'],
position: 2,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['company'].fields['createdAt'],
viewId: viewIdMap['All Companies'],
position: 3,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['company'].fields['employees'],
viewId: viewIdMap['All Companies'],
position: 4,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['company'].fields['linkedinLink'],
viewId: viewIdMap['All Companies'],
position: 5,
isVisible: true,
size: 170,
},
{
fieldMetadataId: objectMetadataMap['company'].fields['address'],
viewId: viewIdMap['All Companies'],
position: 6,
isVisible: true,
size: 170,
},
{
fieldMetadataId: objectMetadataMap['person'].fields['name'],
viewId: viewIdMap['All People'],
position: 0,
isVisible: true,
size: 210,
},
{
fieldMetadataId: objectMetadataMap['person'].fields['email'],
viewId: viewIdMap['All People'],
position: 1,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['person'].fields['company'],
viewId: viewIdMap['All People'],
position: 2,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['person'].fields['phone'],
viewId: viewIdMap['All People'],
position: 3,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['person'].fields['createdAt'],
viewId: viewIdMap['All People'],
position: 4,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['person'].fields['city'],
viewId: viewIdMap['All People'],
position: 5,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['person'].fields['jobTitle'],
viewId: viewIdMap['All People'],
position: 6,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['person'].fields['linkedinLink'],
viewId: viewIdMap['All People'],
position: 7,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['person'].fields['xLink'],
viewId: viewIdMap['All People'],
position: 8,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['opportunity'].fields['amount'],
viewId: viewIdMap['All Opportunities'],
position: 0,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['opportunity'].fields['closeDate'],
viewId: viewIdMap['All Opportunities'],
position: 1,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['opportunity'].fields['probability'],
viewId: viewIdMap['All Opportunities'],
position: 2,
isVisible: true,
size: 150,
},
{
fieldMetadataId: objectMetadataMap['opportunity'].fields['pointOfContact'],
viewId: viewIdMap['All Opportunities'],
position: 3,
isVisible: true,
size: 150,
},
])
.execute();
};
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
import { typeORMCoreModuleOptions } from 'src/database/typeorm/core/core.datasource';
import { EnvironmentModule } from 'src/integrations/environment/environment.module';
import { TypeORMService } from './typeorm.service';
@@ -27,6 +28,7 @@ const coreTypeORMFactory = async (): Promise<TypeOrmModuleOptions> => ({
useFactory: coreTypeORMFactory,
name: 'core',
}),
EnvironmentModule,
],
providers: [TypeORMService],
exports: [TypeORMService],