Standard relation field for custom objects (#13968)

## Introduction
Introducing default standard relation field for custom objects
This commit is contained in:
Paul Rastoin
2025-08-19 13:53:46 +02:00
committed by GitHub
parent a6145f5ea7
commit 86170c705e
13 changed files with 738 additions and 405 deletions
@@ -0,0 +1,97 @@
import {
capitalize,
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
} from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
import { type CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
import { buildDefaultFlatFieldMetadatasForCustomObject } from 'src/engine/metadata-modules/object-metadata/utils/build-default-flat-field-metadatas-for-custom-object.util';
import { buildDefaultRelationFlatFieldMetadatasForCustomObject } from 'src/engine/metadata-modules/object-metadata/utils/build-default-relation-flat-field-metadatas-for-custom-object.util';
type FromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreateArgs =
{
createObjectInput: Omit<CreateObjectInput, 'workspaceId'>;
workspaceId: string;
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
};
export const fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreate =
({
createObjectInput: rawCreateObjectInput,
workspaceId,
existingFlatObjectMetadataMaps,
}: FromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreateArgs): {
flatObjectMetadataToCreate: FlatObjectMetadata;
relationTargetFlatFieldMetadatas: FlatFieldMetadata[];
} => {
const createObjectInput =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
rawCreateObjectInput,
[
'description',
'icon',
'labelPlural',
'labelSingular',
'namePlural',
'nameSingular',
'shortcut',
],
);
const objectMetadataId = v4();
const baseCustomFlatFieldMetadatas =
buildDefaultFlatFieldMetadatasForCustomObject({
objectMetadataId,
workspaceId,
});
const createdAt = new Date();
const flatObjectMetadataToCreate: FlatObjectMetadata = {
createdAt,
flatFieldMetadatas: [],
updatedAt: createdAt,
duplicateCriteria: null,
description: createObjectInput.description ?? null,
flatIndexMetadatas: [],
icon: createObjectInput.icon ?? null,
id: objectMetadataId,
imageIdentifierFieldMetadataId: null,
isActive: true,
isAuditLogged: true,
isCustom: true,
isLabelSyncedWithName: createObjectInput.isLabelSyncedWithName ?? false,
isRemote: createObjectInput.isRemote ?? false,
isSearchable: true,
isSystem: false,
labelIdentifierFieldMetadataId: baseCustomFlatFieldMetadatas.nameField.id,
labelPlural: capitalize(createObjectInput.labelPlural),
labelSingular: capitalize(createObjectInput.labelSingular),
namePlural: createObjectInput.namePlural,
nameSingular: createObjectInput.nameSingular,
shortcut: createObjectInput.shortcut ?? null,
standardId: null,
standardOverrides: null,
uniqueIdentifier: objectMetadataId,
targetTableName: 'DEPRECATED',
workspaceId,
};
const {
standardSourceFlatFieldMetadatas,
standardTargetFlatFieldMetadatas,
} = buildDefaultRelationFlatFieldMetadatasForCustomObject({
existingFlatObjectMetadataMaps,
sourceFlatObjectMetadata: flatObjectMetadataToCreate,
workspaceId,
});
flatObjectMetadataToCreate.flatFieldMetadatas = [
...Object.values(baseCustomFlatFieldMetadatas),
...standardSourceFlatFieldMetadatas,
];
return {
flatObjectMetadataToCreate,
relationTargetFlatFieldMetadatas: standardTargetFlatFieldMetadatas,
};
};
@@ -1,70 +0,0 @@
import {
capitalize,
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
} from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
import { type CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
import { buildDefaultFlatFieldMetadataForCustomObject } from 'src/engine/metadata-modules/object-metadata/utils/build-default-fields-for-custom-object.util';
export const fromCreateObjectInputToFlatObjectMetadata = ({
createObjectInput: rawCreateObjectInput,
workspaceId,
}: {
createObjectInput: Omit<CreateObjectInput, 'workspaceId'>;
workspaceId: string;
}): FlatObjectMetadata => {
const createObjectInput =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
rawCreateObjectInput,
[
'description',
'icon',
'labelPlural',
'labelSingular',
'namePlural',
'nameSingular',
'shortcut',
],
);
const objectMetadataId = v4();
const baseCustomFlatFieldMetadatas =
buildDefaultFlatFieldMetadataForCustomObject({
objectMetadataId,
workspaceId,
});
const createdAt = new Date();
return {
createdAt,
updatedAt: createdAt,
duplicateCriteria: null,
description: createObjectInput.description ?? null,
flatFieldMetadatas: Object.values(baseCustomFlatFieldMetadatas),
flatIndexMetadatas: [],
icon: createObjectInput.icon ?? null,
id: objectMetadataId,
imageIdentifierFieldMetadataId: null,
isActive: true,
isAuditLogged: true,
isCustom: true,
isLabelSyncedWithName: createObjectInput.isLabelSyncedWithName ?? false,
isRemote: createObjectInput.isRemote ?? false,
isSearchable: true,
isSystem: false,
labelIdentifierFieldMetadataId: baseCustomFlatFieldMetadatas.nameField.id,
labelPlural: capitalize(createObjectInput.labelPlural),
labelSingular: capitalize(createObjectInput.labelSingular),
namePlural: createObjectInput.namePlural,
nameSingular: createObjectInput.nameSingular,
shortcut: createObjectInput.shortcut ?? null,
standardId: null,
standardOverrides: null,
uniqueIdentifier: objectMetadataId,
targetTableName: 'DEPRECATED',
workspaceId,
};
};