Integrate relations for remote objects (#4754)

Foreign table id cannot be a foreign key of a base table. But the
current code use foreign keys to link object metadata with activities,
events... So we will:
- create a column without creating a foreign key
- add a comment on the table schema so pg_graphql sees it as a foreign
key

This PR:
- refactor a bit object metadata service so the mutation creation is
separated into an util
- adds the mutation creation for remote object relations
- add a new type of mutation to create a comment

---------

Co-authored-by: Thomas Trompette <thomast@twenty.com>
This commit is contained in:
Thomas Trompette
2024-04-03 14:56:51 +02:00
committed by GitHub
parent 3b72eed2dc
commit 1c6f0eb577
9 changed files with 454 additions and 200 deletions

View File

@ -0,0 +1,175 @@
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
import {
WorkspaceMigrationTableAction,
WorkspaceMigrationColumnActionType,
WorkspaceMigrationColumnCreate,
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
import { computeCustomName } from 'src/engine/utils/compute-custom-name.util';
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
export const buildWorkspaceMigrationsForCustomObject = (
createdObjectMetadata: ObjectMetadataEntity,
activityTargetObjectMetadata: ObjectMetadataEntity,
attachmentObjectMetadata: ObjectMetadataEntity,
eventObjectMetadata: ObjectMetadataEntity,
favoriteObjectMetadata: ObjectMetadataEntity,
): WorkspaceMigrationTableAction[] => [
{
name: computeObjectTargetTable(createdObjectMetadata),
action: 'create',
} satisfies WorkspaceMigrationTableAction,
// Add activity target relation
{
name: computeObjectTargetTable(activityTargetObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
isNullable: true,
} satisfies WorkspaceMigrationColumnCreate,
],
},
{
name: computeObjectTargetTable(activityTargetObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
referencedTableName: computeObjectTargetTable(createdObjectMetadata),
referencedTableColumnName: 'id',
onDelete: RelationOnDeleteAction.CASCADE,
},
],
},
// Add attachment relation
{
name: computeObjectTargetTable(attachmentObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
isNullable: true,
} satisfies WorkspaceMigrationColumnCreate,
],
},
{
name: computeObjectTargetTable(attachmentObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
referencedTableName: computeObjectTargetTable(createdObjectMetadata),
referencedTableColumnName: 'id',
onDelete: RelationOnDeleteAction.CASCADE,
},
],
},
// Add event relation
{
name: computeObjectTargetTable(eventObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
isNullable: true,
} satisfies WorkspaceMigrationColumnCreate,
],
},
{
name: computeObjectTargetTable(eventObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
referencedTableName: computeObjectTargetTable(createdObjectMetadata),
referencedTableColumnName: 'id',
onDelete: RelationOnDeleteAction.CASCADE,
},
],
},
// Add favorite relation
{
name: computeObjectTargetTable(favoriteObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
isNullable: true,
} satisfies WorkspaceMigrationColumnCreate,
],
},
{
name: computeObjectTargetTable(favoriteObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
referencedTableName: computeObjectTargetTable(createdObjectMetadata),
referencedTableColumnName: 'id',
onDelete: RelationOnDeleteAction.CASCADE,
},
],
},
{
name: computeObjectTargetTable(createdObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: 'position',
columnType: 'float',
isNullable: true,
} satisfies WorkspaceMigrationColumnCreate,
],
} satisfies WorkspaceMigrationTableAction,
// This is temporary until we implement mainIdentifier
{
name: computeObjectTargetTable(createdObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: 'name',
columnType: 'text',
defaultValue: "'Untitled'",
} satisfies WorkspaceMigrationColumnCreate,
],
} satisfies WorkspaceMigrationTableAction,
];

View File

@ -0,0 +1,204 @@
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import {
WorkspaceMigrationTableAction,
WorkspaceMigrationColumnActionType,
WorkspaceMigrationColumnCreate,
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
import { computeCustomName } from 'src/engine/utils/compute-custom-name.util';
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
const buildCommentForRemoteObjectForeignKey = (
localObjectMetadataName: string,
remoteObjectMetadataName: string,
schema: string,
): string =>
`@graphql({"totalCount":{"enabled": true},"foreign_keys":[{"local_name":"${localObjectMetadataName}Collection","local_columns":["${remoteObjectMetadataName}Id"],"foreign_name":"${remoteObjectMetadataName}","foreign_schema":"${schema}","foreign_table":"${remoteObjectMetadataName}","foreign_columns":["id"]}]})`;
export const buildWorkspaceMigrationsForRemoteObject = (
createdObjectMetadata: ObjectMetadataEntity,
activityTargetObjectMetadata: ObjectMetadataEntity,
attachmentObjectMetadata: ObjectMetadataEntity,
eventObjectMetadata: ObjectMetadataEntity,
favoriteObjectMetadata: ObjectMetadataEntity,
schema: string,
): WorkspaceMigrationTableAction[] => {
const createdObjectName = createdObjectMetadata.nameSingular;
return [
{
name: computeObjectTargetTable(activityTargetObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
isNullable: true,
} satisfies WorkspaceMigrationColumnCreate,
],
},
{
name: computeObjectTargetTable(activityTargetObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
},
],
},
{
name: computeObjectTargetTable(activityTargetObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE_COMMENT,
comment: buildCommentForRemoteObjectForeignKey(
activityTargetObjectMetadata.nameSingular,
createdObjectName,
schema,
),
},
],
},
// Add attachment relation
{
name: computeObjectTargetTable(attachmentObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
isNullable: true,
} satisfies WorkspaceMigrationColumnCreate,
],
},
{
name: computeObjectTargetTable(attachmentObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
},
],
},
{
name: computeObjectTargetTable(attachmentObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE_COMMENT,
comment: buildCommentForRemoteObjectForeignKey(
attachmentObjectMetadata.nameSingular,
createdObjectName,
schema,
),
},
],
},
// Add event relation
{
name: computeObjectTargetTable(eventObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
isNullable: true,
} satisfies WorkspaceMigrationColumnCreate,
],
},
{
name: computeObjectTargetTable(eventObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
},
],
},
{
name: computeObjectTargetTable(eventObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE_COMMENT,
comment: buildCommentForRemoteObjectForeignKey(
eventObjectMetadata.nameSingular,
createdObjectName,
schema,
),
},
],
},
// Add favorite relation
{
name: computeObjectTargetTable(favoriteObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
isNullable: true,
} satisfies WorkspaceMigrationColumnCreate,
],
},
{
name: computeObjectTargetTable(favoriteObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE,
columnName: `${computeCustomName(
createdObjectMetadata.nameSingular,
false,
)}Id`,
columnType: 'uuid',
},
],
},
{
name: computeObjectTargetTable(favoriteObjectMetadata),
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.CREATE_COMMENT,
comment: buildCommentForRemoteObjectForeignKey(
favoriteObjectMetadata.nameSingular,
createdObjectName,
schema,
),
},
],
},
];
};