Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 42d0fdeeeb | |||
| 8d95166af8 | |||
| 676866a554 | |||
| fc6aafd3c6 |
@@ -25,6 +25,10 @@
|
||||
{
|
||||
"include": "**/serverless/drivers/constants/executor/index.mjs",
|
||||
"outDir": "dist/assets"
|
||||
},
|
||||
{
|
||||
"include": "**/database/clickhouse/migrations/*.sql",
|
||||
"outDir": "dist/src"
|
||||
}
|
||||
],
|
||||
"watchAssets": true
|
||||
|
||||
@@ -30,30 +30,6 @@ async function ensureDatabaseExists() {
|
||||
query: `CREATE DATABASE IF NOT EXISTS "${database}"`,
|
||||
});
|
||||
|
||||
let jsonTypeEnabled = false;
|
||||
|
||||
try {
|
||||
await client.command({
|
||||
query: `SET enable_json_type = 1`,
|
||||
});
|
||||
jsonTypeEnabled = true;
|
||||
} catch (error) {
|
||||
// Intentionally empty - will try alternative method
|
||||
}
|
||||
|
||||
try {
|
||||
await client.command({
|
||||
query: `SET allow_experimental_json_type = 1`,
|
||||
});
|
||||
jsonTypeEnabled = true;
|
||||
} catch (error) {
|
||||
// Intentionally empty - failure handled by jsonTypeEnabled check
|
||||
}
|
||||
|
||||
if (!jsonTypeEnabled) {
|
||||
console.error('Failed to enable JSON type');
|
||||
}
|
||||
|
||||
await client.close();
|
||||
}
|
||||
|
||||
@@ -99,6 +75,9 @@ async function runMigrations() {
|
||||
|
||||
const client = createClient({
|
||||
url: clickhouseUrl(),
|
||||
clickhouse_settings: {
|
||||
allow_experimental_json_type: 1,
|
||||
},
|
||||
});
|
||||
|
||||
await ensureMigrationTable(client);
|
||||
|
||||
+8
-2
@@ -129,8 +129,14 @@ export class MigrateRelationsToFieldMetadataCommand extends ActiveOrSuspendedWor
|
||||
...fieldMetadata,
|
||||
settings: {
|
||||
relationType,
|
||||
onDelete: relationMetadata.onDeleteAction,
|
||||
joinColumnName: joinColumnFieldMetadata?.name,
|
||||
onDelete:
|
||||
relationType === RelationType.MANY_TO_ONE
|
||||
? relationMetadata.onDeleteAction
|
||||
: undefined,
|
||||
joinColumnName:
|
||||
relationType === RelationType.MANY_TO_ONE
|
||||
? joinColumnFieldMetadata?.name
|
||||
: undefined,
|
||||
},
|
||||
relationTargetFieldMetadataId,
|
||||
relationTargetObjectMetadataId,
|
||||
|
||||
+3
@@ -72,6 +72,9 @@ export class AccessTokenService {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
{
|
||||
shouldFailIfMetadataNotFound: false,
|
||||
},
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOne({
|
||||
|
||||
+2
-2
@@ -355,7 +355,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
});
|
||||
|
||||
if (fieldMetadata.type === FieldMetadataType.RELATION) {
|
||||
const isManyToManyRelation =
|
||||
const isManyToOneRelation =
|
||||
(fieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>)
|
||||
.settings?.relationType === RelationType.MANY_TO_ONE;
|
||||
|
||||
@@ -385,7 +385,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.DROP,
|
||||
columnName: isManyToManyRelation
|
||||
columnName: isManyToOneRelation
|
||||
? `${(fieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>).settings?.joinColumnName}`
|
||||
: `${(targetFieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>).settings?.joinColumnName}`,
|
||||
} satisfies WorkspaceMigrationColumnDrop,
|
||||
|
||||
-1
@@ -100,7 +100,6 @@ export class ObjectMetadataFieldRelationService {
|
||||
...sourceFieldMetadata,
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
},
|
||||
relationTargetObjectMetadataId: targetObjectMetadata.id,
|
||||
relationTargetFieldMetadataId: targetFieldMetadata.id,
|
||||
|
||||
+6
@@ -55,6 +55,12 @@ export class RelationColumnActionFactory extends ColumnActionAbstractFactory<Fie
|
||||
return [];
|
||||
}
|
||||
|
||||
if (
|
||||
currentFieldMetadata.settings.relationType === RelationType.ONE_TO_MANY
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const currentJoinColumnName = currentFieldMetadata.settings.joinColumnName;
|
||||
const alteredJoinColumnName = alteredFieldMetadata.settings.joinColumnName;
|
||||
|
||||
|
||||
+235
-118
@@ -1,110 +1,232 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'class-validator';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface';
|
||||
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
|
||||
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
|
||||
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage';
|
||||
import { getJoinColumn } from 'src/engine/twenty-orm/utils/get-join-column.util';
|
||||
import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util';
|
||||
import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util';
|
||||
import { assert } from 'src/utils/assert';
|
||||
|
||||
interface CustomRelationFactory {
|
||||
object: ObjectMetadataEntity;
|
||||
metadata: typeof BaseWorkspaceEntity;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class StandardFieldRelationFactory {
|
||||
createFieldRelationForCustomObject(
|
||||
customObjectFactories: CustomRelationFactory[],
|
||||
context: WorkspaceSyncContext,
|
||||
computeRelationFieldsForCustomObject(
|
||||
customObjectMetadata: ObjectMetadataEntity,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): FieldMetadataEntity<FieldMetadataType.RELATION>[] {
|
||||
return customObjectFactories.flatMap((customObjectFactory) =>
|
||||
this.updateFieldRelationMetadata(
|
||||
customObjectFactory,
|
||||
context,
|
||||
originalObjectMetadataMap,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
createFieldRelationForStandardObject(
|
||||
standardObjectMetadataDefinitions: (typeof BaseWorkspaceEntity)[],
|
||||
context: WorkspaceSyncContext,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): Map<string, FieldMetadataEntity<FieldMetadataType.RELATION>[]> {
|
||||
return standardObjectMetadataDefinitions.reduce(
|
||||
(acc, standardObjectMetadata) => {
|
||||
const workspaceEntityMetadataArgs = metadataArgsStorage.filterEntities(
|
||||
standardObjectMetadata,
|
||||
);
|
||||
|
||||
if (!workspaceEntityMetadataArgs) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
if (
|
||||
isGatedAndNotEnabled(
|
||||
workspaceEntityMetadataArgs.gate,
|
||||
context.featureFlags,
|
||||
)
|
||||
) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
acc.set(
|
||||
workspaceEntityMetadataArgs.standardId,
|
||||
this.updateFieldRelationMetadata(
|
||||
standardObjectMetadata,
|
||||
context,
|
||||
originalObjectMetadataMap,
|
||||
),
|
||||
);
|
||||
|
||||
return acc;
|
||||
},
|
||||
new Map<string, FieldMetadataEntity<FieldMetadataType.RELATION>[]>(),
|
||||
);
|
||||
}
|
||||
|
||||
private updateFieldRelationMetadata(
|
||||
workspaceEntityOrCustomRelationFactory:
|
||||
| typeof BaseWorkspaceEntity
|
||||
| CustomRelationFactory,
|
||||
context: WorkspaceSyncContext,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): FieldMetadataEntity<FieldMetadataType.RELATION>[] {
|
||||
const target =
|
||||
'metadata' in workspaceEntityOrCustomRelationFactory
|
||||
? workspaceEntityOrCustomRelationFactory.metadata
|
||||
: workspaceEntityOrCustomRelationFactory;
|
||||
const workspaceEntity =
|
||||
'metadata' in workspaceEntityOrCustomRelationFactory
|
||||
? metadataArgsStorage.filterExtendedEntities(target)
|
||||
: metadataArgsStorage.filterEntities(target);
|
||||
const workspaceRelationMetadataArgsCollection =
|
||||
metadataArgsStorage.filterRelations(target);
|
||||
metadataArgsStorage.filterRelations(CustomWorkspaceEntity);
|
||||
|
||||
if (!workspaceEntity) {
|
||||
const joinColumnsMetadataArgsCollection =
|
||||
metadataArgsStorage.filterJoinColumns(CustomWorkspaceEntity);
|
||||
|
||||
const objectNameSingular = customObjectMetadata.nameSingular;
|
||||
|
||||
const sourceObjectMetadata = originalObjectMetadataMap[objectNameSingular];
|
||||
|
||||
if (!isDefined(sourceObjectMetadata)) {
|
||||
throw new Error(
|
||||
`Object metadata decorator not found, can't parse ${target.name}`,
|
||||
`Source object ${objectNameSingular} not found in database while parsing ${objectNameSingular} relations`,
|
||||
);
|
||||
}
|
||||
|
||||
return workspaceRelationMetadataArgsCollection.map(
|
||||
(workspaceRelationMetadataArgs) => {
|
||||
const inverseSideTarget =
|
||||
workspaceRelationMetadataArgs.inverseSideTarget();
|
||||
const targetObjectNameSingular = convertClassNameToObjectMetadataName(
|
||||
inverseSideTarget.name,
|
||||
);
|
||||
const targetObjectMetadata =
|
||||
originalObjectMetadataMap[targetObjectNameSingular];
|
||||
|
||||
if (!isDefined(targetObjectMetadata)) {
|
||||
throw new Error(
|
||||
`Target object ${targetObjectNameSingular} not found in database while parsing ${objectNameSingular} relations`,
|
||||
);
|
||||
}
|
||||
|
||||
const sourceFieldMetadataName = workspaceRelationMetadataArgs.name;
|
||||
|
||||
const targetFieldMetadataName =
|
||||
workspaceRelationMetadataArgs.inverseSideFieldKey ??
|
||||
objectNameSingular;
|
||||
|
||||
const targetFieldMetadata = targetObjectMetadata.fields.find(
|
||||
(field) => field.name === targetFieldMetadataName,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
if (!isDefined(targetFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Target field ${targetFieldMetadataName} not found in object ${targetObjectNameSingular} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
const joinColumnName =
|
||||
workspaceRelationMetadataArgs.type === RelationType.MANY_TO_ONE
|
||||
? getJoinColumn(
|
||||
joinColumnsMetadataArgsCollection,
|
||||
workspaceRelationMetadataArgs as WorkspaceRelationMetadataArgs,
|
||||
)
|
||||
: undefined;
|
||||
|
||||
const sourceFieldMetadata = sourceObjectMetadata.fields.find(
|
||||
(field) => field.name === sourceFieldMetadataName,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
if (!isDefined(sourceFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Source field ${sourceFieldMetadataName} not found in object ${sourceFieldMetadata.name} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...sourceFieldMetadata,
|
||||
type: FieldMetadataType.RELATION,
|
||||
settings: {
|
||||
relationType: workspaceRelationMetadataArgs.type,
|
||||
onDelete:
|
||||
workspaceRelationMetadataArgs.type === RelationType.MANY_TO_ONE
|
||||
? workspaceRelationMetadataArgs.onDelete
|
||||
: undefined,
|
||||
joinColumnName,
|
||||
},
|
||||
relationTargetObjectMetadataId: targetObjectMetadata.id,
|
||||
relationTargetFieldMetadataId: targetFieldMetadata.id,
|
||||
isNullable: workspaceRelationMetadataArgs.isNullable,
|
||||
} satisfies FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
computeRelationFieldsForStandardObject(
|
||||
standardObjectMetadataWorkspaceEntity: typeof BaseWorkspaceEntity,
|
||||
context: WorkspaceSyncContext,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): FieldMetadataEntity<FieldMetadataType.RELATION>[] {
|
||||
const workspaceEntityMetadataArgs = metadataArgsStorage.filterEntities(
|
||||
standardObjectMetadataWorkspaceEntity,
|
||||
);
|
||||
|
||||
if (!workspaceEntityMetadataArgs) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (
|
||||
!workspaceRelationMetadataArgsCollection ||
|
||||
isGatedAndNotEnabled(workspaceEntity?.gate, context.featureFlags)
|
||||
isGatedAndNotEnabled(
|
||||
workspaceEntityMetadataArgs.gate,
|
||||
context.featureFlags,
|
||||
)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return workspaceRelationMetadataArgsCollection
|
||||
const sourceObjectNameSingular = workspaceEntityMetadataArgs.nameSingular;
|
||||
|
||||
const workspaceStaticRelationMetadataArgsCollection =
|
||||
metadataArgsStorage.filterRelations(
|
||||
standardObjectMetadataWorkspaceEntity,
|
||||
);
|
||||
|
||||
const workspaceDynamicRelationMetadataArgsCollection =
|
||||
metadataArgsStorage.filterDynamicRelations(
|
||||
standardObjectMetadataWorkspaceEntity,
|
||||
);
|
||||
|
||||
const joinColumnsMetadataArgsCollection =
|
||||
metadataArgsStorage.filterJoinColumns(
|
||||
standardObjectMetadataWorkspaceEntity,
|
||||
);
|
||||
|
||||
if (
|
||||
!isDefined(workspaceStaticRelationMetadataArgsCollection) &&
|
||||
!isDefined(workspaceDynamicRelationMetadataArgsCollection)
|
||||
) {
|
||||
throw new Error(
|
||||
`No relations found for object ${sourceObjectNameSingular}`,
|
||||
);
|
||||
}
|
||||
|
||||
const sourceObjectMetadata =
|
||||
originalObjectMetadataMap[sourceObjectNameSingular];
|
||||
|
||||
if (!isDefined(sourceObjectMetadata)) {
|
||||
throw new Error(
|
||||
`Source object ${sourceObjectNameSingular} not found in database while parsing relations`,
|
||||
);
|
||||
}
|
||||
|
||||
const relationsFromDynamicRelations =
|
||||
workspaceDynamicRelationMetadataArgsCollection
|
||||
.filter(
|
||||
(workspaceDynamicRelationMetadataArgs) =>
|
||||
!isGatedAndNotEnabled(
|
||||
workspaceDynamicRelationMetadataArgs.gate,
|
||||
context.featureFlags,
|
||||
),
|
||||
)
|
||||
.flatMap((workspaceDynamicRelationMetadataArgs) => {
|
||||
const customObjectMetadataItems = Object.values(
|
||||
originalObjectMetadataMap,
|
||||
).filter((objectMetadata) => objectMetadata.isCustom);
|
||||
|
||||
// TODO: this is hacky and needs to be simplified
|
||||
return customObjectMetadataItems.flatMap((targetObjectMetadata) => {
|
||||
const relationMetadataArgs =
|
||||
workspaceDynamicRelationMetadataArgs.argsFactory(
|
||||
targetObjectMetadata,
|
||||
);
|
||||
|
||||
const sourceFieldMetadata = sourceObjectMetadata?.fields.find(
|
||||
(field) => field.name === relationMetadataArgs.name,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
const targetFieldMetadata = targetObjectMetadata?.fields.find(
|
||||
(field) =>
|
||||
field.name ===
|
||||
workspaceDynamicRelationMetadataArgs.inverseSideFieldKey,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
if (!isDefined(sourceFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Source field ${relationMetadataArgs.name} not found in object ${sourceObjectNameSingular} for relation ${relationMetadataArgs.name} of type ${relationMetadataArgs}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!isDefined(targetFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Target field ${workspaceDynamicRelationMetadataArgs.inverseSideFieldKey} not found in object ${targetObjectMetadata.nameSingular} for relation ${relationMetadataArgs.name} of type ${workspaceDynamicRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...sourceFieldMetadata,
|
||||
type: FieldMetadataType.RELATION,
|
||||
settings: {
|
||||
relationType: workspaceDynamicRelationMetadataArgs.type,
|
||||
onDelete:
|
||||
workspaceDynamicRelationMetadataArgs.type ===
|
||||
RelationType.MANY_TO_ONE
|
||||
? workspaceDynamicRelationMetadataArgs.onDelete
|
||||
: undefined,
|
||||
joinColumnName: relationMetadataArgs.joinColumn,
|
||||
},
|
||||
relationTargetObjectMetadataId: targetObjectMetadata.id,
|
||||
relationTargetFieldMetadataId: targetFieldMetadata.id,
|
||||
isNullable: workspaceDynamicRelationMetadataArgs.isNullable,
|
||||
} satisfies FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
});
|
||||
});
|
||||
|
||||
const staticRelations = workspaceStaticRelationMetadataArgsCollection
|
||||
.filter(
|
||||
(workspaceRelationMetadataArgs) =>
|
||||
!isGatedAndNotEnabled(
|
||||
@@ -113,13 +235,6 @@ export class StandardFieldRelationFactory {
|
||||
),
|
||||
)
|
||||
.map((workspaceRelationMetadataArgs) => {
|
||||
// Compute reflect relation metadata
|
||||
const sourceObjectNameSingular =
|
||||
'object' in workspaceEntityOrCustomRelationFactory
|
||||
? workspaceEntityOrCustomRelationFactory.object.nameSingular
|
||||
: convertClassNameToObjectMetadataName(
|
||||
workspaceRelationMetadataArgs.target.name,
|
||||
);
|
||||
const inverseSideTarget =
|
||||
workspaceRelationMetadataArgs.inverseSideTarget();
|
||||
const targetObjectNameSingular = convertClassNameToObjectMetadataName(
|
||||
@@ -127,60 +242,62 @@ export class StandardFieldRelationFactory {
|
||||
);
|
||||
const sourceFieldMetadataName = workspaceRelationMetadataArgs.name;
|
||||
const targetFieldMetadataName =
|
||||
(workspaceRelationMetadataArgs.inverseSideFieldKey as
|
||||
| string
|
||||
| undefined) ?? sourceObjectNameSingular;
|
||||
const sourceObjectMetadata =
|
||||
originalObjectMetadataMap[sourceObjectNameSingular];
|
||||
const joinColumnsMetadataArgsCollection =
|
||||
metadataArgsStorage.filterJoinColumns(target);
|
||||
const joinColumnName = getJoinColumn(
|
||||
joinColumnsMetadataArgsCollection,
|
||||
workspaceRelationMetadataArgs,
|
||||
);
|
||||
workspaceRelationMetadataArgs.inverseSideFieldKey ??
|
||||
sourceObjectNameSingular;
|
||||
|
||||
assert(
|
||||
sourceObjectMetadata,
|
||||
`Source object ${sourceObjectNameSingular} not found in databse for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
|
||||
const targetObjectMetadata =
|
||||
originalObjectMetadataMap[targetObjectNameSingular];
|
||||
|
||||
assert(
|
||||
targetObjectMetadata,
|
||||
`Target object ${targetObjectNameSingular} not found in databse for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
const joinColumnName =
|
||||
workspaceRelationMetadataArgs.type === RelationType.MANY_TO_ONE
|
||||
? getJoinColumn(
|
||||
joinColumnsMetadataArgsCollection,
|
||||
workspaceRelationMetadataArgs as WorkspaceRelationMetadataArgs,
|
||||
)
|
||||
: undefined;
|
||||
|
||||
const sourceFieldMetadata = sourceObjectMetadata?.fields.find(
|
||||
(field) => field.name === sourceFieldMetadataName,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
assert(
|
||||
sourceFieldMetadata,
|
||||
`Source field ${sourceFieldMetadataName} not found in object ${sourceObjectNameSingular} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
if (!isDefined(sourceFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Source field ${sourceFieldMetadataName} not found in object ${sourceObjectNameSingular} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
const targetFieldMetadata = targetObjectMetadata?.fields.find(
|
||||
const targetObjectMetadata =
|
||||
originalObjectMetadataMap[targetObjectNameSingular];
|
||||
|
||||
if (!isDefined(targetObjectMetadata)) {
|
||||
throw new Error(
|
||||
`Target object ${targetObjectNameSingular} not found in database for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
const targetFieldMetadata = targetObjectMetadata.fields.find(
|
||||
(field) => field.name === targetFieldMetadataName,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
assert(
|
||||
targetFieldMetadata,
|
||||
`Target field ${targetFieldMetadataName} not found in object ${targetObjectNameSingular} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
if (!isDefined(targetFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Target field ${targetFieldMetadataName} not found in object ${targetObjectNameSingular} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...sourceFieldMetadata,
|
||||
type: FieldMetadataType.RELATION,
|
||||
settings: {
|
||||
relationType: workspaceRelationMetadataArgs.type,
|
||||
onDelete: workspaceRelationMetadataArgs.onDelete,
|
||||
onDelete:
|
||||
workspaceRelationMetadataArgs.type === RelationType.MANY_TO_ONE
|
||||
? workspaceRelationMetadataArgs.onDelete
|
||||
: undefined,
|
||||
joinColumnName,
|
||||
},
|
||||
relationTargetObjectMetadataId: targetObjectMetadata.id,
|
||||
relationTargetFieldMetadataId: targetFieldMetadata.id,
|
||||
} satisfies FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
});
|
||||
|
||||
return [...staticRelations, ...relationsFromDynamicRelations];
|
||||
}
|
||||
}
|
||||
|
||||
+31
-33
@@ -13,7 +13,7 @@ import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-syn
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
|
||||
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage';
|
||||
import { WorkspaceMigrationFieldRelationFactory } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-field-relation.factory';
|
||||
import {
|
||||
FieldMetadataUpdate,
|
||||
@@ -150,26 +150,30 @@ export class WorkspaceSyncFieldMetadataRelationService {
|
||||
originalObjectMetadataMapByName: Record<string, ObjectMetadataEntity>,
|
||||
storage: WorkspaceSyncStorage,
|
||||
): Promise<void> {
|
||||
// Create standard field metadata map
|
||||
const standardFieldMetadataRelationCollection =
|
||||
this.standardFieldRelationFactory.createFieldRelationForStandardObject(
|
||||
standardObjectMetadataDefinitions,
|
||||
context,
|
||||
originalObjectMetadataMapByName,
|
||||
);
|
||||
|
||||
// Create map of original and standard object metadata by standard ids
|
||||
const originalObjectMetadataMap = mapObjectMetadataByUniqueIdentifier(
|
||||
originalObjectMetadataCollection,
|
||||
);
|
||||
|
||||
// Loop over all standard objects and compare them with the objects in DB
|
||||
for (const [
|
||||
standardObjectId,
|
||||
standardFieldMetadataCollection,
|
||||
] of standardFieldMetadataRelationCollection) {
|
||||
for (const standardObjectMetadataDefinition of standardObjectMetadataDefinitions) {
|
||||
const workspaceEntityMetadataArgs = metadataArgsStorage.filterEntities(
|
||||
standardObjectMetadataDefinition,
|
||||
);
|
||||
|
||||
if (!workspaceEntityMetadataArgs) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const standardFieldMetadataRelationCollection =
|
||||
this.standardFieldRelationFactory.computeRelationFieldsForStandardObject(
|
||||
standardObjectMetadataDefinition,
|
||||
context,
|
||||
originalObjectMetadataMapByName,
|
||||
);
|
||||
|
||||
const originalObjectMetadata =
|
||||
originalObjectMetadataMap[standardObjectId];
|
||||
originalObjectMetadataMap[workspaceEntityMetadataArgs.standardId];
|
||||
|
||||
const originalFieldRelationMetadataCollection =
|
||||
(originalObjectMetadata?.fields.filter(
|
||||
@@ -183,7 +187,7 @@ export class WorkspaceSyncFieldMetadataRelationService {
|
||||
const fieldComparatorResults =
|
||||
this.workspaceFieldRelationComparator.compare(
|
||||
originalFieldRelationMetadataCollection,
|
||||
standardFieldMetadataCollection,
|
||||
standardFieldMetadataRelationCollection,
|
||||
);
|
||||
|
||||
this.storeComparatorResults(fieldComparatorResults, storage);
|
||||
@@ -196,25 +200,22 @@ export class WorkspaceSyncFieldMetadataRelationService {
|
||||
originalObjectMetadataMapByName: Record<string, ObjectMetadataEntity>,
|
||||
storage: WorkspaceSyncStorage,
|
||||
): Promise<void> {
|
||||
// Create standard field metadata collection
|
||||
const customFieldMetadataRelationCollection =
|
||||
this.standardFieldRelationFactory.createFieldRelationForCustomObject(
|
||||
customObjectMetadataCollection.map((objectMetadata) => ({
|
||||
object: objectMetadata,
|
||||
metadata: CustomWorkspaceEntity,
|
||||
})),
|
||||
context,
|
||||
originalObjectMetadataMapByName,
|
||||
);
|
||||
|
||||
// Loop over all custom objects from the DB and compare their fields with standard fields
|
||||
for (const customObjectMetadata of customObjectMetadataCollection) {
|
||||
/**
|
||||
* COMPARE FIELD METADATA
|
||||
*/
|
||||
const originalFieldRelationMetadataCollection =
|
||||
(customObjectMetadata.fields.filter(
|
||||
(field) => field.type === FieldMetadataType.RELATION,
|
||||
) ?? []) as FieldMetadataEntity<FieldMetadataType.RELATION>[];
|
||||
|
||||
const customFieldMetadataRelationCollection =
|
||||
this.standardFieldRelationFactory.computeRelationFieldsForCustomObject(
|
||||
customObjectMetadata,
|
||||
originalObjectMetadataMapByName,
|
||||
);
|
||||
|
||||
const fieldComparatorResults =
|
||||
this.workspaceFieldRelationComparator.compare(
|
||||
customObjectMetadata.fields as FieldMetadataEntity<FieldMetadataType.RELATION>[],
|
||||
originalFieldRelationMetadataCollection,
|
||||
customFieldMetadataRelationCollection,
|
||||
);
|
||||
|
||||
@@ -233,9 +234,6 @@ export class WorkspaceSyncFieldMetadataRelationService {
|
||||
await objectMetadataRepository.find({
|
||||
where: {
|
||||
workspaceId: context.workspaceId,
|
||||
fields: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
},
|
||||
},
|
||||
relations: ['dataSource', 'fields'],
|
||||
});
|
||||
|
||||
+8
@@ -3,6 +3,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
|
||||
@@ -69,6 +70,7 @@ export class AttachmentWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconCircleUser',
|
||||
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
|
||||
inverseSideFieldKey: 'authoredAttachments',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
author: Relation<WorkspaceMemberWorkspaceEntity> | null;
|
||||
@@ -84,6 +86,7 @@ export class AttachmentWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconNotes',
|
||||
inverseSideTarget: () => TaskWorkspaceEntity,
|
||||
inverseSideFieldKey: 'attachments',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
task: Relation<TaskWorkspaceEntity> | null;
|
||||
@@ -99,6 +102,7 @@ export class AttachmentWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconNotes',
|
||||
inverseSideTarget: () => NoteWorkspaceEntity,
|
||||
inverseSideFieldKey: 'attachments',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
note: Relation<NoteWorkspaceEntity> | null;
|
||||
@@ -114,6 +118,7 @@ export class AttachmentWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconUser',
|
||||
inverseSideTarget: () => PersonWorkspaceEntity,
|
||||
inverseSideFieldKey: 'attachments',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
person: Relation<PersonWorkspaceEntity> | null;
|
||||
@@ -129,6 +134,7 @@ export class AttachmentWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
inverseSideTarget: () => CompanyWorkspaceEntity,
|
||||
inverseSideFieldKey: 'attachments',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
company: Relation<CompanyWorkspaceEntity> | null;
|
||||
@@ -144,6 +150,7 @@ export class AttachmentWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
inverseSideTarget: () => OpportunityWorkspaceEntity,
|
||||
inverseSideFieldKey: 'attachments',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
opportunity: Relation<OpportunityWorkspaceEntity> | null;
|
||||
@@ -163,6 +170,7 @@ export class AttachmentWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
}),
|
||||
inverseSideTarget: () => CustomWorkspaceEntity,
|
||||
inverseSideFieldKey: 'attachments',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
custom: Relation<CustomWorkspaceEntity>;
|
||||
}
|
||||
|
||||
+2
@@ -3,6 +3,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
|
||||
@@ -45,6 +46,7 @@ export class BlocklistWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconCircleUser',
|
||||
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
|
||||
inverseSideFieldKey: 'blocklist',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
workspaceMember: Relation<WorkspaceMemberWorkspaceEntity>;
|
||||
|
||||
|
||||
+3
@@ -3,6 +3,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
|
||||
@@ -57,6 +58,7 @@ export class CalendarChannelEventAssociationWorkspaceEntity extends BaseWorkspac
|
||||
icon: 'IconCalendar',
|
||||
inverseSideTarget: () => CalendarChannelWorkspaceEntity,
|
||||
inverseSideFieldKey: 'calendarChannelEventAssociations',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
calendarChannel: Relation<CalendarChannelWorkspaceEntity>;
|
||||
|
||||
@@ -72,6 +74,7 @@ export class CalendarChannelEventAssociationWorkspaceEntity extends BaseWorkspac
|
||||
icon: 'IconCalendar',
|
||||
inverseSideTarget: () => CalendarEventWorkspaceEntity,
|
||||
inverseSideFieldKey: 'calendarChannelEventAssociations',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
calendarEvent: Relation<CalendarEventWorkspaceEntity>;
|
||||
|
||||
|
||||
+1
@@ -307,6 +307,7 @@ export class CalendarChannelWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconUserCircle',
|
||||
inverseSideTarget: () => ConnectedAccountWorkspaceEntity,
|
||||
inverseSideFieldKey: 'calendarChannels',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
connectedAccount: Relation<ConnectedAccountWorkspaceEntity>;
|
||||
|
||||
|
||||
+4
@@ -3,6 +3,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
|
||||
@@ -111,6 +112,7 @@ export class CalendarEventParticipantWorkspaceEntity extends BaseWorkspaceEntity
|
||||
icon: 'IconCalendar',
|
||||
inverseSideTarget: () => CalendarEventWorkspaceEntity,
|
||||
inverseSideFieldKey: 'calendarEventParticipants',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
calendarEvent: Relation<CalendarEventWorkspaceEntity>;
|
||||
|
||||
@@ -125,6 +127,7 @@ export class CalendarEventParticipantWorkspaceEntity extends BaseWorkspaceEntity
|
||||
icon: 'IconUser',
|
||||
inverseSideTarget: () => PersonWorkspaceEntity,
|
||||
inverseSideFieldKey: 'calendarEventParticipants',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
person: Relation<PersonWorkspaceEntity> | null;
|
||||
@@ -140,6 +143,7 @@ export class CalendarEventParticipantWorkspaceEntity extends BaseWorkspaceEntity
|
||||
icon: 'IconUser',
|
||||
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
|
||||
inverseSideFieldKey: 'calendarEventParticipants',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workspaceMember: Relation<WorkspaceMemberWorkspaceEntity> | null;
|
||||
|
||||
+1
@@ -117,6 +117,7 @@ export class ConnectedAccountWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconUserCircle',
|
||||
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
|
||||
inverseSideFieldKey: 'connectedAccounts',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
accountOwner: Relation<WorkspaceMemberWorkspaceEntity>;
|
||||
|
||||
|
||||
+11
@@ -61,6 +61,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconCircleUser',
|
||||
inverseSideFieldKey: 'favorites',
|
||||
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
forWorkspaceMember: Relation<WorkspaceMemberWorkspaceEntity>;
|
||||
@@ -76,6 +77,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconUser',
|
||||
inverseSideTarget: () => PersonWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
person: Relation<PersonWorkspaceEntity> | null;
|
||||
@@ -91,6 +93,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
inverseSideTarget: () => CompanyWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
company: Relation<CompanyWorkspaceEntity> | null;
|
||||
@@ -106,6 +109,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconFolder',
|
||||
inverseSideTarget: () => FavoriteFolderWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
favoriteFolder: Relation<FavoriteFolderWorkspaceEntity> | null;
|
||||
@@ -121,6 +125,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconTargetArrow',
|
||||
inverseSideTarget: () => OpportunityWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
opportunity: Relation<OpportunityWorkspaceEntity> | null;
|
||||
@@ -136,6 +141,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconSettingsAutomation',
|
||||
inverseSideTarget: () => WorkflowWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workflow: Relation<WorkflowWorkspaceEntity> | null;
|
||||
@@ -151,6 +157,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconSettingsAutomation',
|
||||
inverseSideTarget: () => WorkflowVersionWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workflowVersion: Relation<WorkflowVersionWorkspaceEntity> | null;
|
||||
@@ -166,6 +173,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconSettingsAutomation',
|
||||
inverseSideTarget: () => WorkflowRunWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workflowRun: Relation<WorkflowRunWorkspaceEntity> | null;
|
||||
@@ -181,6 +189,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconCheckbox',
|
||||
inverseSideTarget: () => TaskWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
task: Relation<TaskWorkspaceEntity> | null;
|
||||
@@ -196,6 +205,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconNotes',
|
||||
inverseSideTarget: () => NoteWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
note: Relation<NoteWorkspaceEntity> | null;
|
||||
@@ -231,6 +241,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
}),
|
||||
inverseSideTarget: () => CustomWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
custom: Relation<CustomWorkspaceEntity>;
|
||||
}
|
||||
|
||||
+3
@@ -3,6 +3,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
|
||||
@@ -93,6 +94,7 @@ export class MessageChannelMessageAssociationWorkspaceEntity extends BaseWorkspa
|
||||
icon: 'IconHash',
|
||||
inverseSideTarget: () => MessageChannelWorkspaceEntity,
|
||||
inverseSideFieldKey: 'messageChannelMessageAssociations',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
messageChannel: Relation<MessageChannelWorkspaceEntity> | null;
|
||||
@@ -108,6 +110,7 @@ export class MessageChannelMessageAssociationWorkspaceEntity extends BaseWorkspa
|
||||
icon: 'IconHash',
|
||||
inverseSideTarget: () => MessageWorkspaceEntity,
|
||||
inverseSideFieldKey: 'messageChannelMessageAssociations',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
message: Relation<MessageWorkspaceEntity> | null;
|
||||
|
||||
+1
@@ -359,6 +359,7 @@ export class MessageChannelWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconUserCircle',
|
||||
inverseSideTarget: () => ConnectedAccountWorkspaceEntity,
|
||||
inverseSideFieldKey: 'messageChannels',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
connectedAccount: Relation<ConnectedAccountWorkspaceEntity>;
|
||||
|
||||
|
||||
+2
@@ -3,6 +3,7 @@ import { Relation } from 'typeorm';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
|
||||
@@ -44,6 +45,7 @@ export class MessageFolderWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconMessage',
|
||||
inverseSideTarget: () => MessageChannelWorkspaceEntity,
|
||||
inverseSideFieldKey: 'messageFolders',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
messageChannel: Relation<MessageChannelWorkspaceEntity>;
|
||||
|
||||
|
||||
+4
@@ -3,6 +3,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
|
||||
@@ -73,6 +74,7 @@ export class MessageParticipantWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconMessage',
|
||||
inverseSideTarget: () => MessageWorkspaceEntity,
|
||||
inverseSideFieldKey: 'messageParticipants',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
message: Relation<MessageWorkspaceEntity>;
|
||||
|
||||
@@ -87,6 +89,7 @@ export class MessageParticipantWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconUser',
|
||||
inverseSideTarget: () => PersonWorkspaceEntity,
|
||||
inverseSideFieldKey: 'messageParticipants',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
person: Relation<PersonWorkspaceEntity> | null;
|
||||
@@ -102,6 +105,7 @@ export class MessageParticipantWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconCircleUser',
|
||||
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
|
||||
inverseSideFieldKey: 'messageParticipants',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workspaceMember: Relation<WorkspaceMemberWorkspaceEntity> | null;
|
||||
|
||||
+6
@@ -2,6 +2,7 @@ import { msg } from '@lingui/core/macro';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
|
||||
@@ -37,6 +38,7 @@ export class NoteTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconNotes',
|
||||
inverseSideTarget: () => NoteWorkspaceEntity,
|
||||
inverseSideFieldKey: 'noteTargets',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
note: Relation<NoteWorkspaceEntity> | null;
|
||||
@@ -52,6 +54,7 @@ export class NoteTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconUser',
|
||||
inverseSideTarget: () => PersonWorkspaceEntity,
|
||||
inverseSideFieldKey: 'noteTargets',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
person: Relation<PersonWorkspaceEntity> | null;
|
||||
@@ -67,6 +70,7 @@ export class NoteTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
inverseSideTarget: () => CompanyWorkspaceEntity,
|
||||
inverseSideFieldKey: 'noteTargets',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
company: Relation<CompanyWorkspaceEntity> | null;
|
||||
@@ -82,6 +86,7 @@ export class NoteTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconTargetArrow',
|
||||
inverseSideTarget: () => OpportunityWorkspaceEntity,
|
||||
inverseSideFieldKey: 'noteTargets',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
opportunity: Relation<OpportunityWorkspaceEntity> | null;
|
||||
@@ -101,6 +106,7 @@ export class NoteTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
}),
|
||||
inverseSideTarget: () => CustomWorkspaceEntity,
|
||||
inverseSideFieldKey: 'noteTargets',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
custom: Relation<CustomWorkspaceEntity>;
|
||||
}
|
||||
|
||||
@@ -185,6 +185,7 @@ export class PersonWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
inverseSideTarget: () => CompanyWorkspaceEntity,
|
||||
inverseSideFieldKey: 'people',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
company: Relation<CompanyWorkspaceEntity> | null;
|
||||
|
||||
+6
@@ -2,6 +2,7 @@ import { msg } from '@lingui/core/macro';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
|
||||
@@ -37,6 +38,7 @@ export class TaskTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconCheckbox',
|
||||
inverseSideTarget: () => TaskWorkspaceEntity,
|
||||
inverseSideFieldKey: 'taskTargets',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
task: Relation<TaskWorkspaceEntity> | null;
|
||||
@@ -52,6 +54,7 @@ export class TaskTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconUser',
|
||||
inverseSideTarget: () => PersonWorkspaceEntity,
|
||||
inverseSideFieldKey: 'taskTargets',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
person: Relation<PersonWorkspaceEntity> | null;
|
||||
@@ -67,6 +70,7 @@ export class TaskTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
inverseSideTarget: () => CompanyWorkspaceEntity,
|
||||
inverseSideFieldKey: 'taskTargets',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
company: Relation<CompanyWorkspaceEntity> | null;
|
||||
@@ -82,6 +86,7 @@ export class TaskTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconTargetArrow',
|
||||
inverseSideTarget: () => OpportunityWorkspaceEntity,
|
||||
inverseSideFieldKey: 'taskTargets',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
opportunity: Relation<OpportunityWorkspaceEntity> | null;
|
||||
@@ -101,6 +106,7 @@ export class TaskTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
}),
|
||||
inverseSideTarget: () => CustomWorkspaceEntity,
|
||||
inverseSideFieldKey: 'taskTargets',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
custom: Relation<CustomWorkspaceEntity>;
|
||||
}
|
||||
|
||||
+2
@@ -3,6 +3,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
|
||||
@@ -92,6 +93,7 @@ export class AuditLogWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconCircleUser',
|
||||
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
|
||||
inverseSideFieldKey: 'auditLogs',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workspaceMember: Relation<WorkspaceMemberWorkspaceEntity> | null;
|
||||
|
||||
+11
@@ -3,6 +3,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
|
||||
@@ -106,6 +107,7 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconCircleUser',
|
||||
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
|
||||
inverseSideFieldKey: 'timelineActivities',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workspaceMember: Relation<WorkspaceMemberWorkspaceEntity> | null;
|
||||
@@ -121,6 +123,7 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconUser',
|
||||
inverseSideTarget: () => PersonWorkspaceEntity,
|
||||
inverseSideFieldKey: 'timelineActivities',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
person: Relation<PersonWorkspaceEntity> | null;
|
||||
@@ -136,6 +139,7 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
inverseSideTarget: () => CompanyWorkspaceEntity,
|
||||
inverseSideFieldKey: 'timelineActivities',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
company: Relation<CompanyWorkspaceEntity> | null;
|
||||
@@ -151,6 +155,7 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconTargetArrow',
|
||||
inverseSideTarget: () => OpportunityWorkspaceEntity,
|
||||
inverseSideFieldKey: 'timelineActivities',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
opportunity: Relation<OpportunityWorkspaceEntity> | null;
|
||||
@@ -166,6 +171,7 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconTargetArrow',
|
||||
inverseSideTarget: () => NoteWorkspaceEntity,
|
||||
inverseSideFieldKey: 'timelineActivities',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
note: Relation<NoteWorkspaceEntity> | null;
|
||||
@@ -181,6 +187,7 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconTargetArrow',
|
||||
inverseSideTarget: () => TaskWorkspaceEntity,
|
||||
inverseSideFieldKey: 'timelineActivities',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
task: Relation<TaskWorkspaceEntity> | null;
|
||||
@@ -196,6 +203,7 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconTargetArrow',
|
||||
inverseSideTarget: () => WorkflowWorkspaceEntity,
|
||||
inverseSideFieldKey: 'timelineActivities',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workflow: Relation<WorkflowWorkspaceEntity> | null;
|
||||
@@ -211,6 +219,7 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconTargetArrow',
|
||||
inverseSideTarget: () => WorkflowVersionWorkspaceEntity,
|
||||
inverseSideFieldKey: 'timelineActivities',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workflowVersion: Relation<WorkflowVersionWorkspaceEntity> | null;
|
||||
@@ -226,6 +235,7 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconTargetArrow',
|
||||
inverseSideTarget: () => WorkflowRunWorkspaceEntity,
|
||||
inverseSideFieldKey: 'timelineActivities',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workflowRun: Relation<WorkflowRunWorkspaceEntity> | null;
|
||||
@@ -245,6 +255,7 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
}),
|
||||
inverseSideTarget: () => CustomWorkspaceEntity,
|
||||
inverseSideFieldKey: 'timelineActivities',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
custom: Relation<CustomWorkspaceEntity>;
|
||||
}
|
||||
|
||||
+2
@@ -3,6 +3,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
|
||||
@@ -45,6 +46,7 @@ export class WorkflowEventListenerWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconSettingsAutomation',
|
||||
inverseSideTarget: () => WorkflowWorkspaceEntity,
|
||||
inverseSideFieldKey: 'eventListeners',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workflow: Relation<WorkflowWorkspaceEntity>;
|
||||
|
||||
+2
@@ -169,6 +169,7 @@ export class WorkflowRunWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconVersions',
|
||||
inverseSideTarget: () => WorkflowVersionWorkspaceEntity,
|
||||
inverseSideFieldKey: 'runs',
|
||||
onDelete: RelationOnDeleteAction.SET_NULL,
|
||||
})
|
||||
workflowVersion: Relation<WorkflowVersionWorkspaceEntity>;
|
||||
|
||||
@@ -183,6 +184,7 @@ export class WorkflowRunWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconSettingsAutomation',
|
||||
inverseSideTarget: () => WorkflowWorkspaceEntity,
|
||||
inverseSideFieldKey: 'runs',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
workflow: Relation<WorkflowWorkspaceEntity>;
|
||||
|
||||
|
||||
+1
@@ -127,6 +127,7 @@ export class WorkflowVersionWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
icon: 'IconSettingsAutomation',
|
||||
inverseSideTarget: () => WorkflowWorkspaceEntity,
|
||||
inverseSideFieldKey: 'versions',
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
workflow: Relation<WorkflowWorkspaceEntity>;
|
||||
|
||||
Reference in New Issue
Block a user