Morph relation : migration builder (#13173)
This PR will create the migration to be run for the morph relations - We created a dedicated util to generate the column name and refactored a little the code in order to have less dependencies and a clearer devX (updated the snapshot that changed because of this) - Moved the `createMigrationActions` to its own util as well - Created the `MorphRelationColumnActionFactory` based on the relation one --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -2,9 +2,10 @@ module.exports = {
|
|||||||
plugins: ['@stylistic'],
|
plugins: ['@stylistic'],
|
||||||
extends: ['../../.eslintrc.global.cjs'],
|
extends: ['../../.eslintrc.global.cjs'],
|
||||||
ignorePatterns: [
|
ignorePatterns: [
|
||||||
'src/engine/workspace-manager/demo-objects-prefill-data/**',
|
'src/engine/workspace-manager/dev-seeder/data/constants/**',
|
||||||
'src/engine/seeder/data-seeds/**',
|
'src/engine/workspace-manager/dev-seeder/data/seeds/**',
|
||||||
'src/engine/seeder/metadata-seeds/**',
|
'src/utils/email-providers.ts',
|
||||||
|
'src/engine/core-modules/i18n/locales/generated/**',
|
||||||
'src/engine/core-modules/serverless/drivers/constants/base-typescript-project/src/index.ts',
|
'src/engine/core-modules/serverless/drivers/constants/base-typescript-project/src/index.ts',
|
||||||
],
|
],
|
||||||
overrides: [
|
overrides: [
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import { isDefined } from 'class-validator';
|
|
||||||
import omit from 'lodash.omit';
|
import omit from 'lodash.omit';
|
||||||
import { FieldMetadataType } from 'twenty-shared/types';
|
import { FieldMetadataType } from 'twenty-shared/types';
|
||||||
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
@ -19,6 +19,8 @@ import { prepareCustomFieldMetadataForCreation } from 'src/engine/metadata-modul
|
|||||||
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
|
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
|
||||||
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
||||||
import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util';
|
import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util';
|
||||||
|
import { computeMorphRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-relation-field-join-column-name.util';
|
||||||
|
import { computeRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-relation-field-join-column-name.util';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FieldMetadataMorphRelationService {
|
export class FieldMetadataMorphRelationService {
|
||||||
@ -59,12 +61,26 @@ export class FieldMetadataMorphRelationService {
|
|||||||
const fieldsCreated: FieldMetadataEntity[] = [];
|
const fieldsCreated: FieldMetadataEntity[] = [];
|
||||||
|
|
||||||
for (const relation of morphRelationsCreationPayload) {
|
for (const relation of morphRelationsCreationPayload) {
|
||||||
|
const targetObjectMetadata =
|
||||||
|
objectMetadataMaps.byId[relation.targetObjectMetadataId];
|
||||||
|
|
||||||
|
if (!isDefined(targetObjectMetadata)) {
|
||||||
|
throw new FieldMetadataException(
|
||||||
|
'Target object metadata does not exist in the object metadata maps',
|
||||||
|
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const relationFieldMetadataForCreate =
|
const relationFieldMetadataForCreate =
|
||||||
await this.fieldMetadataRelationService.addCustomRelationFieldMetadataForCreation(
|
await this.fieldMetadataRelationService.addCustomRelationFieldMetadataForCreation(
|
||||||
{
|
{
|
||||||
fieldMetadataInput: fieldMetadataForCreate,
|
fieldMetadataInput: fieldMetadataForCreate,
|
||||||
relationCreationPayload: relation,
|
relationCreationPayload: relation,
|
||||||
objectMetadata,
|
joinColumnName: computeMorphRelationFieldJoinColumnName({
|
||||||
|
name: fieldMetadataForCreate.name,
|
||||||
|
targetObjectMetadataNameSingular:
|
||||||
|
targetObjectMetadata.nameSingular,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -109,7 +125,9 @@ export class FieldMetadataMorphRelationService {
|
|||||||
? RelationType.MANY_TO_ONE
|
? RelationType.MANY_TO_ONE
|
||||||
: RelationType.ONE_TO_MANY,
|
: RelationType.ONE_TO_MANY,
|
||||||
},
|
},
|
||||||
objectMetadata,
|
joinColumnName: computeRelationFieldJoinColumnName({
|
||||||
|
name: targetFieldMetadataToCreate.name,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { Injectable, ValidationError } from '@nestjs/common';
|
|||||||
import { plainToInstance } from 'class-transformer';
|
import { plainToInstance } from 'class-transformer';
|
||||||
import { IsEnum, IsString, IsUUID, validateOrReject } from 'class-validator';
|
import { IsEnum, IsString, IsUUID, validateOrReject } from 'class-validator';
|
||||||
import { FieldMetadataType } from 'twenty-shared/types';
|
import { FieldMetadataType } from 'twenty-shared/types';
|
||||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
@ -28,6 +28,7 @@ import { validateMetadataNameOrThrow } from 'src/engine/metadata-modules/utils/v
|
|||||||
import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util';
|
import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util';
|
||||||
import { isFieldMetadataInterfaceOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
|
import { isFieldMetadataInterfaceOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
|
||||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||||
|
import { computeRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-relation-field-join-column-name.util';
|
||||||
|
|
||||||
export class RelationCreationPayloadValidation {
|
export class RelationCreationPayloadValidation {
|
||||||
@IsUUID()
|
@IsUUID()
|
||||||
@ -103,7 +104,9 @@ export class FieldMetadataRelationService {
|
|||||||
? RelationType.MANY_TO_ONE
|
? RelationType.MANY_TO_ONE
|
||||||
: RelationType.ONE_TO_MANY,
|
: RelationType.ONE_TO_MANY,
|
||||||
},
|
},
|
||||||
objectMetadata,
|
joinColumnName: computeRelationFieldJoinColumnName({
|
||||||
|
name: targetFieldMetadataToCreate.name,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
// todo better type
|
// todo better type
|
||||||
@ -285,11 +288,11 @@ export class FieldMetadataRelationService {
|
|||||||
addCustomRelationFieldMetadataForCreation({
|
addCustomRelationFieldMetadataForCreation({
|
||||||
fieldMetadataInput,
|
fieldMetadataInput,
|
||||||
relationCreationPayload,
|
relationCreationPayload,
|
||||||
objectMetadata,
|
joinColumnName,
|
||||||
}: {
|
}: {
|
||||||
fieldMetadataInput: CreateFieldInput;
|
fieldMetadataInput: CreateFieldInput;
|
||||||
relationCreationPayload: CreateFieldInput['relationCreationPayload'];
|
relationCreationPayload: CreateFieldInput['relationCreationPayload'];
|
||||||
objectMetadata: ObjectMetadataItemWithFieldMaps;
|
joinColumnName: string;
|
||||||
}) {
|
}) {
|
||||||
const isRelation =
|
const isRelation =
|
||||||
isFieldMetadataInterfaceOfType(
|
isFieldMetadataInterfaceOfType(
|
||||||
@ -309,13 +312,6 @@ export class FieldMetadataRelationService {
|
|||||||
|
|
||||||
const defaultIcon = 'IconRelationOneToMany';
|
const defaultIcon = 'IconRelationOneToMany';
|
||||||
|
|
||||||
const joinColumnName = isFieldMetadataInterfaceOfType(
|
|
||||||
fieldMetadataInput,
|
|
||||||
FieldMetadataType.MORPH_RELATION,
|
|
||||||
)
|
|
||||||
? `${fieldMetadataInput.name}${capitalize(objectMetadata.nameSingular)}Id`
|
|
||||||
: `${fieldMetadataInput.name}Id`;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...fieldMetadataInput,
|
...fieldMetadataInput,
|
||||||
icon: fieldMetadataInput.icon ?? defaultIcon,
|
icon: fieldMetadataInput.icon ?? defaultIcon,
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import {
|
|||||||
computeColumnName,
|
computeColumnName,
|
||||||
computeCompositeColumnName,
|
computeCompositeColumnName,
|
||||||
} from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
} from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||||
|
import { createMigrationActions } from 'src/engine/metadata-modules/field-metadata/utils/create-migration-actions.util';
|
||||||
import { generateRatingOptions } from 'src/engine/metadata-modules/field-metadata/utils/generate-rating-optionts.util';
|
import { generateRatingOptions } from 'src/engine/metadata-modules/field-metadata/utils/generate-rating-optionts.util';
|
||||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||||
import { isSelectOrMultiSelectFieldMetadata } from 'src/engine/metadata-modules/field-metadata/utils/is-select-or-multi-select-field-metadata.util';
|
import { isSelectOrMultiSelectFieldMetadata } from 'src/engine/metadata-modules/field-metadata/utils/is-select-or-multi-select-field-metadata.util';
|
||||||
@ -54,9 +55,9 @@ import { WorkspaceMigrationFactory } from 'src/engine/metadata-modules/workspace
|
|||||||
import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service';
|
import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service';
|
||||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||||
import { isFieldMetadataEntityOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
|
|
||||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
|
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
|
||||||
import { ViewService } from 'src/modules/view/services/view.service';
|
import { ViewService } from 'src/modules/view/services/view.service';
|
||||||
|
import { computeRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-relation-field-join-column-name.util';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntity> {
|
export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntity> {
|
||||||
@ -578,15 +579,14 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||||||
|
|
||||||
createdFieldMetadatas.push(...createdFieldMetadataItems);
|
createdFieldMetadatas.push(...createdFieldMetadataItems);
|
||||||
|
|
||||||
const fieldMigrationActions = await this.createMigrationActions({
|
const fieldMigrationActions = await createMigrationActions({
|
||||||
createdFieldMetadataItems,
|
createdFieldMetadataItems,
|
||||||
objectMetadataMap: objectMetadataMaps.byId,
|
objectMetadataMap: objectMetadataMaps.byId,
|
||||||
isRemoteCreation: fieldMetadataInput.isRemoteCreation ?? false,
|
isRemoteCreation: fieldMetadataInput.isRemoteCreation ?? false,
|
||||||
|
workspaceMigrationFactory: this.workspaceMigrationFactory,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (fieldMetadataInput.type !== FieldMetadataType.MORPH_RELATION) {
|
migrationActions.push(...fieldMigrationActions);
|
||||||
migrationActions.push(...fieldMigrationActions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,7 +675,9 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||||||
{
|
{
|
||||||
fieldMetadataInput: fieldMetadataForCreate,
|
fieldMetadataInput: fieldMetadataForCreate,
|
||||||
relationCreationPayload: fieldMetadataInput.relationCreationPayload,
|
relationCreationPayload: fieldMetadataInput.relationCreationPayload,
|
||||||
objectMetadata,
|
joinColumnName: computeRelationFieldJoinColumnName({
|
||||||
|
name: fieldMetadataForCreate.name,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -707,56 +709,4 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createMigrationActions({
|
|
||||||
createdFieldMetadataItems,
|
|
||||||
objectMetadataMap,
|
|
||||||
isRemoteCreation,
|
|
||||||
}: {
|
|
||||||
createdFieldMetadataItems: FieldMetadataEntity[];
|
|
||||||
objectMetadataMap: ObjectMetadataMaps['byId'];
|
|
||||||
isRemoteCreation: boolean;
|
|
||||||
}): Promise<WorkspaceMigrationTableAction[]> {
|
|
||||||
if (isRemoteCreation) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const migrationActions: WorkspaceMigrationTableAction[] = [];
|
|
||||||
|
|
||||||
for (const createdFieldMetadata of createdFieldMetadataItems) {
|
|
||||||
if (
|
|
||||||
isFieldMetadataEntityOfType(
|
|
||||||
createdFieldMetadata,
|
|
||||||
FieldMetadataType.RELATION,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
const relationType = createdFieldMetadata.settings?.relationType;
|
|
||||||
|
|
||||||
if (relationType === RelationType.ONE_TO_MANY) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const objectMetadata =
|
|
||||||
objectMetadataMap[createdFieldMetadata.objectMetadataId];
|
|
||||||
|
|
||||||
if (!isDefined(objectMetadata)) {
|
|
||||||
throw new FieldMetadataException(
|
|
||||||
'Object metadata does not exist',
|
|
||||||
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
migrationActions.push({
|
|
||||||
name: computeObjectTargetTable(objectMetadata),
|
|
||||||
action: WorkspaceMigrationTableActionType.ALTER,
|
|
||||||
columns: this.workspaceMigrationFactory.createColumnActions(
|
|
||||||
WorkspaceMigrationColumnActionType.CREATE,
|
|
||||||
createdFieldMetadata,
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return migrationActions;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { capitalize } from 'twenty-shared/utils';
|
||||||
|
|
||||||
|
type ComputeMorphRelationFieldJoinColumnNameArgs = {
|
||||||
|
name: string;
|
||||||
|
targetObjectMetadataNameSingular: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const computeMorphRelationFieldJoinColumnName = ({
|
||||||
|
name,
|
||||||
|
targetObjectMetadataNameSingular,
|
||||||
|
}: ComputeMorphRelationFieldJoinColumnNameArgs) => {
|
||||||
|
return `${name}${capitalize(targetObjectMetadataNameSingular)}Id`;
|
||||||
|
};
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
type ComputeRelationFieldJoinColumnNameArgs = {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const computeRelationFieldJoinColumnName = ({
|
||||||
|
name,
|
||||||
|
}: ComputeRelationFieldJoinColumnNameArgs) => {
|
||||||
|
return `${name}Id`;
|
||||||
|
};
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
import { FieldMetadataType } from 'twenty-shared/types';
|
||||||
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
|
|
||||||
|
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||||
|
|
||||||
|
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||||
|
import {
|
||||||
|
FieldMetadataException,
|
||||||
|
FieldMetadataExceptionCode,
|
||||||
|
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
|
||||||
|
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
||||||
|
import {
|
||||||
|
WorkspaceMigrationColumnActionType,
|
||||||
|
WorkspaceMigrationTableAction,
|
||||||
|
WorkspaceMigrationTableActionType,
|
||||||
|
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||||
|
import { WorkspaceMigrationFactory } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.factory';
|
||||||
|
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||||
|
import { isFieldMetadataEntityOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
|
||||||
|
|
||||||
|
export const createMigrationActions = async ({
|
||||||
|
createdFieldMetadataItems,
|
||||||
|
objectMetadataMap,
|
||||||
|
isRemoteCreation,
|
||||||
|
workspaceMigrationFactory,
|
||||||
|
}: {
|
||||||
|
createdFieldMetadataItems: FieldMetadataEntity[];
|
||||||
|
objectMetadataMap: ObjectMetadataMaps['byId'];
|
||||||
|
isRemoteCreation: boolean;
|
||||||
|
workspaceMigrationFactory: WorkspaceMigrationFactory;
|
||||||
|
}): Promise<WorkspaceMigrationTableAction[]> => {
|
||||||
|
if (isRemoteCreation) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const migrationActions: WorkspaceMigrationTableAction[] = [];
|
||||||
|
|
||||||
|
for (const createdFieldMetadata of createdFieldMetadataItems) {
|
||||||
|
if (
|
||||||
|
isFieldMetadataEntityOfType(
|
||||||
|
createdFieldMetadata,
|
||||||
|
FieldMetadataType.RELATION,
|
||||||
|
) ||
|
||||||
|
isFieldMetadataEntityOfType(
|
||||||
|
createdFieldMetadata,
|
||||||
|
FieldMetadataType.MORPH_RELATION,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
const relationType = createdFieldMetadata.settings?.relationType;
|
||||||
|
|
||||||
|
if (relationType === RelationType.ONE_TO_MANY) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const objectMetadata =
|
||||||
|
objectMetadataMap[createdFieldMetadata.objectMetadataId];
|
||||||
|
|
||||||
|
if (!isDefined(objectMetadata)) {
|
||||||
|
throw new FieldMetadataException(
|
||||||
|
'Object metadata does not exist',
|
||||||
|
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
migrationActions.push({
|
||||||
|
name: computeObjectTargetTable(objectMetadata),
|
||||||
|
action: WorkspaceMigrationTableActionType.ALTER,
|
||||||
|
columns: workspaceMigrationFactory.createColumnActions(
|
||||||
|
WorkspaceMigrationColumnActionType.CREATE,
|
||||||
|
createdFieldMetadata,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return migrationActions;
|
||||||
|
};
|
||||||
@ -3,30 +3,93 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||||||
import { FieldMetadataType } from 'twenty-shared/types';
|
import { FieldMetadataType } from 'twenty-shared/types';
|
||||||
|
|
||||||
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
|
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
|
||||||
|
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||||
import { WorkspaceColumnActionOptions } from 'src/engine/metadata-modules/workspace-migration/interfaces/workspace-column-action-options.interface';
|
import { WorkspaceColumnActionOptions } from 'src/engine/metadata-modules/workspace-migration/interfaces/workspace-column-action-options.interface';
|
||||||
|
|
||||||
import { ColumnActionAbstractFactory } from 'src/engine/metadata-modules/workspace-migration/factories/column-action-abstract.factory';
|
import { ColumnActionAbstractFactory } from 'src/engine/metadata-modules/workspace-migration/factories/column-action-abstract.factory';
|
||||||
|
import { fieldMetadataTypeToColumnType } from 'src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util';
|
||||||
import {
|
import {
|
||||||
|
WorkspaceMigrationColumnActionType,
|
||||||
WorkspaceMigrationColumnAlter,
|
WorkspaceMigrationColumnAlter,
|
||||||
WorkspaceMigrationColumnCreate,
|
WorkspaceMigrationColumnCreate,
|
||||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||||
|
import {
|
||||||
|
WorkspaceMigrationException,
|
||||||
|
WorkspaceMigrationExceptionCode,
|
||||||
|
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.exception';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MorphRelationColumnActionFactory extends ColumnActionAbstractFactory<FieldMetadataType.MORPH_RELATION> {
|
export class MorphRelationColumnActionFactory extends ColumnActionAbstractFactory<FieldMetadataType.MORPH_RELATION> {
|
||||||
protected readonly logger = new Logger(MorphRelationColumnActionFactory.name);
|
protected readonly logger = new Logger(MorphRelationColumnActionFactory.name);
|
||||||
|
|
||||||
protected handleCreateAction(
|
protected handleCreateAction(
|
||||||
_fieldMetadata: FieldMetadataInterface<FieldMetadataType.MORPH_RELATION>,
|
fieldMetadata: FieldMetadataInterface<FieldMetadataType.MORPH_RELATION>,
|
||||||
_options?: WorkspaceColumnActionOptions,
|
_options?: WorkspaceColumnActionOptions,
|
||||||
): WorkspaceMigrationColumnCreate[] {
|
): WorkspaceMigrationColumnCreate[] {
|
||||||
return [];
|
if (!fieldMetadata.settings || !fieldMetadata.settings.joinColumnName) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const joinColumnName = fieldMetadata.settings.joinColumnName;
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
action: WorkspaceMigrationColumnActionType.CREATE,
|
||||||
|
columnName: joinColumnName,
|
||||||
|
columnType: fieldMetadataTypeToColumnType(FieldMetadataType.UUID),
|
||||||
|
isArray: false,
|
||||||
|
isNullable: fieldMetadata.isNullable ?? true,
|
||||||
|
isUnique: false,
|
||||||
|
defaultValue: null,
|
||||||
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected handleAlterAction(
|
protected handleAlterAction(
|
||||||
_currentFieldMetadata: FieldMetadataInterface<FieldMetadataType.MORPH_RELATION>,
|
currentFieldMetadata: FieldMetadataInterface<FieldMetadataType.MORPH_RELATION>,
|
||||||
_alteredFieldMetadata: FieldMetadataInterface<FieldMetadataType.MORPH_RELATION>,
|
alteredFieldMetadata: FieldMetadataInterface<FieldMetadataType.MORPH_RELATION>,
|
||||||
_options?: WorkspaceColumnActionOptions,
|
_options?: WorkspaceColumnActionOptions,
|
||||||
): WorkspaceMigrationColumnAlter[] {
|
): WorkspaceMigrationColumnAlter[] {
|
||||||
return [];
|
if (!currentFieldMetadata.settings || !alteredFieldMetadata.settings) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
currentFieldMetadata.settings.relationType === RelationType.ONE_TO_MANY
|
||||||
|
) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentJoinColumnName = currentFieldMetadata.settings.joinColumnName;
|
||||||
|
const alteredJoinColumnName = alteredFieldMetadata.settings.joinColumnName;
|
||||||
|
|
||||||
|
if (!currentJoinColumnName || !alteredJoinColumnName) {
|
||||||
|
throw new WorkspaceMigrationException(
|
||||||
|
`Column name not found for current or altered field metadata`,
|
||||||
|
WorkspaceMigrationExceptionCode.INVALID_FIELD_METADATA,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
action: WorkspaceMigrationColumnActionType.ALTER,
|
||||||
|
currentColumnDefinition: {
|
||||||
|
columnName: currentJoinColumnName,
|
||||||
|
columnType: fieldMetadataTypeToColumnType(FieldMetadataType.UUID),
|
||||||
|
isArray: false,
|
||||||
|
isNullable: currentFieldMetadata.isNullable ?? true,
|
||||||
|
isUnique: false,
|
||||||
|
defaultValue: null,
|
||||||
|
},
|
||||||
|
alteredColumnDefinition: {
|
||||||
|
columnName: alteredJoinColumnName,
|
||||||
|
columnType: fieldMetadataTypeToColumnType(FieldMetadataType.UUID),
|
||||||
|
isArray: false,
|
||||||
|
isNullable: alteredFieldMetadata.isNullable ?? true,
|
||||||
|
isUnique: false,
|
||||||
|
defaultValue: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,7 +60,7 @@ exports[`Field metadata morph relation creation should fail relation MANY_TO_ONE
|
|||||||
"exceptionEventId": "mocked-exception-id",
|
"exceptionEventId": "mocked-exception-id",
|
||||||
"userFriendlyMessage": "An error occurred.",
|
"userFriendlyMessage": "An error occurred.",
|
||||||
},
|
},
|
||||||
"message": "Object metadata relation target not found for relation creation payload",
|
"message": "Target object metadata does not exist in the object metadata maps",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
@ -153,7 +153,7 @@ exports[`Field metadata morph relation creation should fail relation ONE_TO_MANY
|
|||||||
"exceptionEventId": "mocked-exception-id",
|
"exceptionEventId": "mocked-exception-id",
|
||||||
"userFriendlyMessage": "An error occurred.",
|
"userFriendlyMessage": "An error occurred.",
|
||||||
},
|
},
|
||||||
"message": "Object metadata relation target not found for relation creation payload",
|
"message": "Target object metadata does not exist in the object metadata maps",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -149,7 +149,7 @@ describe('createOne FieldMetadataService morph relation fields', () => {
|
|||||||
|
|
||||||
if (isManyToOne) {
|
if (isManyToOne) {
|
||||||
expect(createdField.settings?.joinColumnName).toBe(
|
expect(createdField.settings?.joinColumnName).toBe(
|
||||||
'ownerOpportunityForMorphRelationId',
|
'ownerPersonForMorphRelationId',
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
expect(createdField.settings?.joinColumnName).toBeUndefined();
|
expect(createdField.settings?.joinColumnName).toBeUndefined();
|
||||||
|
|||||||
Reference in New Issue
Block a user