-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: manually implement joinColumn (#6022)
This PR introduce a new decorator named `@WorkspaceJoinColumn`, the goal of this one is to manually declare the join columns inside the workspace entities, so we don't have to rely on `ObjectRecord` type. This decorator can be used that way: ```typescript @WorkspaceRelation({ standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.company, type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'ActivityTarget company', icon: 'IconBuildingSkyscraper', inverseSideTarget: () => CompanyWorkspaceEntity, inverseSideFieldKey: 'activityTargets', }) @WorkspaceIsNullable() company: Relation<CompanyWorkspaceEntity> | null; // The argument is the name of the relation above @WorkspaceJoinColumn('company') companyId: string | null; ```
- Loading branch information
Showing
64 changed files
with
427 additions
and
243 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
packages/twenty-server/src/engine/twenty-orm/decorators/workspace-join-column.decorator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; | ||
|
||
export function WorkspaceJoinColumn( | ||
relationPropertyKey: string, | ||
): PropertyDecorator { | ||
return (object, propertyKey) => { | ||
metadataArgsStorage.addJoinColumns({ | ||
target: object.constructor, | ||
relationName: relationPropertyKey, | ||
joinColumn: propertyKey.toString(), | ||
}); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
...server/src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
export interface WorkspaceJoinColumnsMetadataArgs { | ||
/** | ||
* Class to which relation is applied. | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/ban-types | ||
readonly target: Function; | ||
|
||
/** | ||
* Relation name. | ||
*/ | ||
readonly relationName: string; | ||
|
||
/** | ||
* Relation label. | ||
*/ | ||
readonly joinColumn: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { WorkspaceJoinColumnsMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface'; | ||
import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface'; | ||
|
||
import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; | ||
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; | ||
|
||
export const getJoinColumn = ( | ||
joinColumnsMetadataArgsCollection: WorkspaceJoinColumnsMetadataArgs[], | ||
relationMetadataArgs: WorkspaceRelationMetadataArgs, | ||
opposite = false, | ||
): string | null => { | ||
if ( | ||
relationMetadataArgs.type === RelationMetadataType.ONE_TO_MANY || | ||
relationMetadataArgs.type === RelationMetadataType.MANY_TO_MANY | ||
) { | ||
return null; | ||
} | ||
|
||
const inverseSideTarget = relationMetadataArgs.inverseSideTarget(); | ||
const inverseSideJoinColumnsMetadataArgsCollection = | ||
metadataArgsStorage.filterJoinColumns(inverseSideTarget); | ||
const filteredJoinColumnsMetadataArgsCollection = | ||
joinColumnsMetadataArgsCollection.filter( | ||
(joinColumnsMetadataArgs) => | ||
joinColumnsMetadataArgs.relationName === relationMetadataArgs.name, | ||
); | ||
const oppositeFilteredJoinColumnsMetadataArgsCollection = | ||
inverseSideJoinColumnsMetadataArgsCollection.filter( | ||
(joinColumnsMetadataArgs) => | ||
joinColumnsMetadataArgs.relationName === relationMetadataArgs.name, | ||
); | ||
|
||
if ( | ||
filteredJoinColumnsMetadataArgsCollection.length > 0 && | ||
oppositeFilteredJoinColumnsMetadataArgsCollection.length > 0 | ||
) { | ||
throw new Error( | ||
`Join column for ${relationMetadataArgs.name} relation is present on both sides`, | ||
); | ||
} | ||
|
||
// If we're in a ONE_TO_ONE relation and there are no join columns, we need to find the join column on the inverse side | ||
if ( | ||
relationMetadataArgs.type === RelationMetadataType.ONE_TO_ONE && | ||
filteredJoinColumnsMetadataArgsCollection.length === 0 && | ||
!opposite | ||
) { | ||
const inverseSideRelationMetadataArgsCollection = | ||
metadataArgsStorage.filterRelations(inverseSideTarget); | ||
const inverseSideRelationMetadataArgs = | ||
inverseSideRelationMetadataArgsCollection.find( | ||
(inverseSideRelationMetadataArgs) => | ||
inverseSideRelationMetadataArgs.inverseSideFieldKey === | ||
relationMetadataArgs.name, | ||
); | ||
|
||
if (!inverseSideRelationMetadataArgs) { | ||
throw new Error( | ||
`Inverse side join column of relation ${relationMetadataArgs.name} is missing`, | ||
); | ||
} | ||
|
||
return getJoinColumn( | ||
inverseSideJoinColumnsMetadataArgsCollection, | ||
inverseSideRelationMetadataArgs, | ||
// Avoid infinite recursion | ||
true, | ||
); | ||
} | ||
|
||
// Check if there are multiple join columns for the relation | ||
if (filteredJoinColumnsMetadataArgsCollection.length > 1) { | ||
throw new Error( | ||
`Multiple join columns found for relation ${relationMetadataArgs.name}`, | ||
); | ||
} | ||
|
||
const joinColumnsMetadataArgs = filteredJoinColumnsMetadataArgsCollection[0]; | ||
|
||
if (!joinColumnsMetadataArgs) { | ||
throw new Error( | ||
`Join column is missing for relation ${relationMetadataArgs.name}`, | ||
); | ||
} | ||
|
||
return joinColumnsMetadataArgs.joinColumn; | ||
}; |
Oops, something went wrong.