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:
@@ -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],
|
||||
|
||||
Reference in New Issue
Block a user