feat: workspace health type fix (#3890)
* feat: workspace health type fix * Fix --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -140,6 +140,27 @@ export class DatabaseStructureService {
|
||||
});
|
||||
}
|
||||
|
||||
getFieldMetadataTypeFromPostgresDataType(
|
||||
postgresDataType: string,
|
||||
): FieldMetadataType | null {
|
||||
const mainDataSource = this.typeORMService.getMainDataSource();
|
||||
|
||||
for (const type in FieldMetadataType) {
|
||||
const typeORMType = fieldMetadataTypeToColumnType(
|
||||
FieldMetadataType[type],
|
||||
) as ColumnType;
|
||||
const dataType = mainDataSource.driver.normalizeType({
|
||||
type: typeORMType,
|
||||
});
|
||||
|
||||
if (postgresDataType === dataType) {
|
||||
return FieldMetadataType[type];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
getPostgresDefault(
|
||||
fieldMetadataType: FieldMetadataType,
|
||||
defaultValue: FieldMetadataDefaultValue | null,
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { EntityManager } from 'typeorm';
|
||||
|
||||
import {
|
||||
WorkspaceHealthColumnIssue,
|
||||
WorkspaceHealthIssueType,
|
||||
} from 'src/workspace/workspace-health/interfaces/workspace-health-issue.interface';
|
||||
import { WorkspaceMigrationBuilderAction } from 'src/workspace/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/metadata/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceMigrationEntity } from 'src/metadata/workspace-migration/workspace-migration.entity';
|
||||
import { WorkspaceMigrationFieldFactory } from 'src/workspace/workspace-migration-builder/factories/workspace-migration-field.factory';
|
||||
|
||||
import { DatabaseStructureService } from './database-structure.service';
|
||||
|
||||
type WorkspaceHealthTypeIssue =
|
||||
WorkspaceHealthColumnIssue<WorkspaceHealthIssueType.COLUMN_DATA_TYPE_CONFLICT>;
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceFixTypeService {
|
||||
constructor(
|
||||
private readonly workspaceMigrationFieldFactory: WorkspaceMigrationFieldFactory,
|
||||
private readonly databaseStructureService: DatabaseStructureService,
|
||||
) {}
|
||||
|
||||
async fix(
|
||||
manager: EntityManager,
|
||||
objectMetadataCollection: ObjectMetadataEntity[],
|
||||
issues: WorkspaceHealthTypeIssue[],
|
||||
): Promise<Partial<WorkspaceMigrationEntity>[]> {
|
||||
const workspaceMigrations: Partial<WorkspaceMigrationEntity>[] = [];
|
||||
|
||||
for (const issue of issues) {
|
||||
switch (issue.type) {
|
||||
case WorkspaceHealthIssueType.COLUMN_DATA_TYPE_CONFLICT: {
|
||||
const columnNullabilityWorkspaceMigrations =
|
||||
await this.fixColumnTypeIssues(
|
||||
objectMetadataCollection,
|
||||
issues.filter(
|
||||
(issue) =>
|
||||
issue.type ===
|
||||
WorkspaceHealthIssueType.COLUMN_DATA_TYPE_CONFLICT,
|
||||
) as WorkspaceHealthColumnIssue<WorkspaceHealthIssueType.COLUMN_DATA_TYPE_CONFLICT>[],
|
||||
);
|
||||
|
||||
workspaceMigrations.push(...columnNullabilityWorkspaceMigrations);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return workspaceMigrations;
|
||||
}
|
||||
|
||||
private async fixColumnTypeIssues(
|
||||
objectMetadataCollection: ObjectMetadataEntity[],
|
||||
issues: WorkspaceHealthColumnIssue<WorkspaceHealthIssueType.COLUMN_DATA_TYPE_CONFLICT>[],
|
||||
): Promise<Partial<WorkspaceMigrationEntity>[]> {
|
||||
const fieldMetadataUpdateCollection = issues.map((issue) => {
|
||||
if (!issue.columnStructure?.dataType) {
|
||||
throw new Error('Column structure data type is missing');
|
||||
}
|
||||
|
||||
const type =
|
||||
this.databaseStructureService.getFieldMetadataTypeFromPostgresDataType(
|
||||
issue.columnStructure?.dataType,
|
||||
);
|
||||
|
||||
if (!type) {
|
||||
throw new Error("Can't find field metadata type from column structure");
|
||||
}
|
||||
|
||||
return {
|
||||
current: {
|
||||
...issue.fieldMetadata,
|
||||
type,
|
||||
},
|
||||
altered: issue.fieldMetadata,
|
||||
};
|
||||
});
|
||||
|
||||
return this.workspaceMigrationFieldFactory.create(
|
||||
objectMetadataCollection,
|
||||
fieldMetadataUpdateCollection,
|
||||
WorkspaceMigrationBuilderAction.UPDATE,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -7,14 +7,19 @@ import { WorkspaceHealthIssue } from 'src/workspace/workspace-health/interfaces/
|
||||
|
||||
import { WorkspaceMigrationEntity } from 'src/metadata/workspace-migration/workspace-migration.entity';
|
||||
import { ObjectMetadataEntity } from 'src/metadata/object-metadata/object-metadata.entity';
|
||||
import { isWorkspaceHealthNullableIssue } from 'src/workspace/workspace-health/utils/is-workspace-health-issue-type.util';
|
||||
import {
|
||||
isWorkspaceHealthNullableIssue,
|
||||
isWorkspaceHealthTypeIssue,
|
||||
} from 'src/workspace/workspace-health/utils/is-workspace-health-issue-type.util';
|
||||
|
||||
import { WorkspaceFixNullableService } from './workspace-fix-nullable.service';
|
||||
import { WorkspaceFixTypeService } from './workspace-fix-type.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceFixService {
|
||||
constructor(
|
||||
private readonly workspaceFixNullableService: WorkspaceFixNullableService,
|
||||
private readonly workspaceFixTypeService: WorkspaceFixTypeService,
|
||||
) {}
|
||||
|
||||
async fix(
|
||||
@ -30,6 +35,12 @@ export class WorkspaceFixService {
|
||||
isWorkspaceHealthNullableIssue(issue.type),
|
||||
),
|
||||
},
|
||||
[WorkspaceHealthFixKind.Type]: {
|
||||
service: this.workspaceFixTypeService,
|
||||
issues: issues.filter((issue) =>
|
||||
isWorkspaceHealthTypeIssue(issue.type),
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
return services[type].service.fix(
|
||||
|
||||
@ -5,3 +5,9 @@ export const isWorkspaceHealthNullableIssue = (
|
||||
): type is WorkspaceHealthIssueType.COLUMN_NULLABILITY_CONFLICT => {
|
||||
return type === WorkspaceHealthIssueType.COLUMN_NULLABILITY_CONFLICT;
|
||||
};
|
||||
|
||||
export const isWorkspaceHealthTypeIssue = (
|
||||
type: WorkspaceHealthIssueType,
|
||||
): type is WorkspaceHealthIssueType.COLUMN_DATA_TYPE_CONFLICT => {
|
||||
return type === WorkspaceHealthIssueType.COLUMN_DATA_TYPE_CONFLICT;
|
||||
};
|
||||
|
||||
@ -14,6 +14,7 @@ import { WorkspaceMigrationRunnerModule } from 'src/workspace/workspace-migratio
|
||||
|
||||
import { WorkspaceFixService } from './services/workspace-fix.service';
|
||||
import { WorkspaceFixNullableService } from './services/workspace-fix-nullable.service';
|
||||
import { WorkspaceFixTypeService } from './services/workspace-fix-type.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -31,6 +32,7 @@ import { WorkspaceFixNullableService } from './services/workspace-fix-nullable.s
|
||||
FieldMetadataHealthService,
|
||||
RelationMetadataHealthService,
|
||||
WorkspaceFixNullableService,
|
||||
WorkspaceFixTypeService,
|
||||
WorkspaceFixService,
|
||||
],
|
||||
exports: [WorkspaceHealthService],
|
||||
|
||||
Reference in New Issue
Block a user