CreateFieldInput transpilation to FlatFieldMetadata, FlatFieldMetadata validation (#13493)

# Introduction
Following https://github.com/twentyhq/twenty/pull/13420

What has been done:
- `CreateFieldInput` transpilation to `FlatFieldMetadata`
- `FlatFieldMetadata` validator service
- A lof of transpilation utils from `input` to `flatObject` or
`flatField`
- Created dedicated v2 api metadata services
- Introducing `inferDeletionFromMissingObjectFieldIndex` in the builder,
to avoid diffing every object and field of the current workspace we
allow only generating create/update migration operations, usefull when
passing by the api metadata


## We still need to in another PR:
- Implement a strong unit test coverage and critical functions and
services
- Finalize flat field metadata validation exception for `options`
`defaultValue` `settings` and `relations`
- Finalize `flatObjectMetadata` validation and v2 service refactor
- Plug the new service when feature flag is enabled
This commit is contained in:
Paul Rastoin
2025-07-30 15:08:11 +02:00
committed by GitHub
parent 0e4e3acaba
commit 29a4f4d685
41 changed files with 1346 additions and 351 deletions
@@ -6,7 +6,6 @@ exports[`Workspace migration builder field actions test suite It should build a
[
{
"flatFieldMetadata": {
"createdAt": Any<ClockDate>,
"defaultValue": null,
"description": "default flat field metadata description",
"flatRelationTargetFieldMetadata": null,
@@ -30,14 +29,10 @@ exports[`Workspace migration builder field actions test suite It should build a
"standardOverrides": null,
"type": "TEXT",
"uniqueIdentifier": "field-metadata-unique-identifier-1",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -58,7 +53,6 @@ exports[`Workspace migration builder field actions test suite It should build a
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "object-metadata-unique-identifier-1",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "delete_field",
@@ -70,7 +64,6 @@ exports[`Workspace migration builder field actions test suite It should build an
[
{
"flatFieldMetadata": {
"createdAt": Any<ClockDate>,
"defaultValue": null,
"description": "default flat field metadata description",
"flatRelationTargetFieldMetadata": null,
@@ -94,14 +87,10 @@ exports[`Workspace migration builder field actions test suite It should build an
"standardOverrides": null,
"type": "TEXT",
"uniqueIdentifier": "field-metadata-unique-identifier-1",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -122,7 +111,6 @@ exports[`Workspace migration builder field actions test suite It should build an
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "object-metadata-unique-identifier-1",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "create_field",
@@ -134,11 +122,9 @@ exports[`Workspace migration builder field actions test suite It should build an
[
{
"flatFieldMetadata": {
"createdAt": Any<ClockDate>,
"defaultValue": null,
"description": "default flat field metadata description",
"flatRelationTargetFieldMetadata": {
"createdAt": Any<ClockDate>,
"defaultValue": null,
"description": "default flat field metadata description",
"flatRelationTargetFieldMetadata": null,
@@ -162,14 +148,10 @@ exports[`Workspace migration builder field actions test suite It should build an
"standardOverrides": null,
"type": "RELATION",
"uniqueIdentifier": "field-metadata-unique-identifier-2",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"flatRelationTargetObjectMetadata": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"flatFieldMetadatas": [],
"flatIndexMetadatas": [],
"icon": "icon",
@@ -192,7 +174,6 @@ exports[`Workspace migration builder field actions test suite It should build an
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "object-metadata-unique-identifier-2",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"icon": "icon",
@@ -214,14 +195,10 @@ exports[`Workspace migration builder field actions test suite It should build an
"standardOverrides": null,
"type": "RELATION",
"uniqueIdentifier": "field-metadata-unique-identifier-1",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -242,7 +219,6 @@ exports[`Workspace migration builder field actions test suite It should build an
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "object-metadata-unique-identifier-1",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "create_field",
@@ -254,7 +230,6 @@ exports[`Workspace migration builder field actions test suite It should build an
[
{
"flatFieldMetadata": {
"createdAt": Any<ClockDate>,
"defaultValue": null,
"description": "new description",
"flatRelationTargetFieldMetadata": null,
@@ -278,14 +253,10 @@ exports[`Workspace migration builder field actions test suite It should build an
"standardOverrides": null,
"type": "TEXT",
"uniqueIdentifier": "field-metadata-unique-identifier-1",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -306,7 +277,6 @@ exports[`Workspace migration builder field actions test suite It should build an
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "object-metadata-unique-identifier-1",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "update_field",
@@ -341,7 +311,6 @@ exports[`Workspace migration builder field actions test suite It should build an
[
{
"flatFieldMetadata": {
"createdAt": Any<ClockDate>,
"defaultValue": null,
"description": "new description",
"flatRelationTargetFieldMetadata": null,
@@ -365,14 +334,10 @@ exports[`Workspace migration builder field actions test suite It should build an
"standardOverrides": null,
"type": "RELATION",
"uniqueIdentifier": "field-metadata-unique-identifier-1",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -393,7 +358,6 @@ exports[`Workspace migration builder field actions test suite It should build an
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "object-metadata-unique-identifier-1",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "update_field",
@@ -511,10 +475,7 @@ exports[`Workspace migration builder object actions test suite It should build a
{
"createFieldActions": [],
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -535,7 +496,6 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "pomme",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "create_object",
@@ -549,7 +509,6 @@ exports[`Workspace migration builder object actions test suite It should build a
"createFieldActions": [
{
"flatFieldMetadata": {
"createdAt": Any<ClockDate>,
"defaultValue": null,
"description": "default flat field metadata description",
"flatRelationTargetFieldMetadata": null,
@@ -573,14 +532,10 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"type": "TEXT",
"uniqueIdentifier": "field_0",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -601,14 +556,12 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "pomme",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "create_field",
},
{
"flatFieldMetadata": {
"createdAt": Any<ClockDate>,
"defaultValue": null,
"description": "default flat field metadata description",
"flatRelationTargetFieldMetadata": null,
@@ -632,14 +585,10 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"type": "TEXT",
"uniqueIdentifier": "field_1",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -660,14 +609,12 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "pomme",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "create_field",
},
{
"flatFieldMetadata": {
"createdAt": Any<ClockDate>,
"defaultValue": null,
"description": "default flat field metadata description",
"flatRelationTargetFieldMetadata": null,
@@ -691,14 +638,10 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"type": "TEXT",
"uniqueIdentifier": "field_2",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -719,14 +662,12 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "pomme",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "create_field",
},
{
"flatFieldMetadata": {
"createdAt": Any<ClockDate>,
"defaultValue": null,
"description": "default flat field metadata description",
"flatRelationTargetFieldMetadata": null,
@@ -750,14 +691,10 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"type": "TEXT",
"uniqueIdentifier": "field_3",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -778,14 +715,12 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "pomme",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "create_field",
},
{
"flatFieldMetadata": {
"createdAt": Any<ClockDate>,
"defaultValue": null,
"description": "default flat field metadata description",
"flatRelationTargetFieldMetadata": null,
@@ -809,14 +744,10 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"type": "TEXT",
"uniqueIdentifier": "field_4",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -837,17 +768,13 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "pomme",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "create_field",
},
],
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -868,7 +795,6 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "pomme",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "create_object",
@@ -897,10 +823,7 @@ exports[`Workspace migration builder object actions test suite It should build a
[
{
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -921,7 +844,6 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "pomme",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "delete_object",
@@ -933,10 +855,7 @@ exports[`Workspace migration builder object actions test suite It should build a
[
{
"flatObjectMetadataWithoutFields": {
"createdAt": Any<ClockDate>,
"dataSourceId": Any<String>,
"description": "default flat object metadata description",
"duplicateCriteria": [],
"icon": "icon",
"id": Any<String>,
"imageIdentifierFieldMetadataId": Any<String>,
@@ -957,7 +876,6 @@ exports[`Workspace migration builder object actions test suite It should build a
"standardOverrides": null,
"targetTableName": "",
"uniqueIdentifier": "pomme",
"updatedAt": Any<ClockDate>,
"workspaceId": Any<String>,
},
"type": "update_object",
@@ -19,9 +19,11 @@ export class WorkspaceMigrationBuilderV2Service {
build({
objectMetadataFromToInputs,
workspaceId,
inferDeletionFromMissingObjectFieldIndex = true,
}: {
objectMetadataFromToInputs: FromTo<FlatObjectMetadata[]>;
workspaceId: string;
inferDeletionFromMissingObjectFieldIndex?: boolean;
}): WorkspaceMigrationV2 {
const {
created: createdObjectMetadata,
@@ -44,32 +46,36 @@ export class WorkspaceMigrationBuilderV2Service {
);
const deletedObjectWorkspaceMigrationDeleteFieldActions =
deletedObjectMetadata.flatMap((flatObjectMetadata) =>
flatObjectMetadata.flatFieldMetadatas.map((flatFieldMetadata) =>
getWorkspaceMigrationV2FieldDeleteAction({
flatFieldMetadata,
flatObjectMetadata,
}),
),
);
inferDeletionFromMissingObjectFieldIndex
? deletedObjectMetadata.flatMap((flatObjectMetadata) =>
flatObjectMetadata.flatFieldMetadatas.map((flatFieldMetadata) =>
getWorkspaceMigrationV2FieldDeleteAction({
flatFieldMetadata,
flatObjectMetadata,
}),
),
)
: [];
const updatedObjectMetadataDeletedCreatedUpdatedFieldMatrix =
const objectMetadataDeletedCreatedUpdatedFields =
computeUpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix(
updatedObjectMetadata,
);
const fieldWorkspaceMigrationActions =
buildWorkspaceMigrationV2FieldActions(
updatedObjectMetadataDeletedCreatedUpdatedFieldMatrix,
);
buildWorkspaceMigrationV2FieldActions({
inferDeletionFromMissingObjectFieldIndex,
objectMetadataDeletedCreatedUpdatedFields,
});
const updatedObjectMetadataIndexDeletedCreatedUpdatedMatrix =
const objectMetadataDeletedCreatedUpdatedIndex =
computeUpdatedObjectMetadataDeletedCreatedUpdatedIndexMatrix(
updatedObjectMetadata,
);
const indexWorkspaceMigrationActions = buildWorkspaceMigrationIndexActions(
updatedObjectMetadataIndexDeletedCreatedUpdatedMatrix,
);
const indexWorkspaceMigrationActions = buildWorkspaceMigrationIndexActions({
objectMetadataDeletedCreatedUpdatedIndex,
inferDeletionFromMissingObjectFieldIndex,
});
return {
workspaceId,
@@ -10,9 +10,14 @@ import {
getWorkspaceMigrationV2FieldDeleteAction,
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-field-actions';
export const buildWorkspaceMigrationV2FieldActions = (
objectMetadataDeletedCreatedUpdatedFields: UpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix[],
): WorkspaceMigrationFieldActionV2[] => {
type BuildWorkspaceMigrationV2FieldActionsArgs = {
inferDeletionFromMissingObjectFieldIndex: boolean;
objectMetadataDeletedCreatedUpdatedFields: UpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix[];
};
export const buildWorkspaceMigrationV2FieldActions = ({
inferDeletionFromMissingObjectFieldIndex,
objectMetadataDeletedCreatedUpdatedFields,
}: BuildWorkspaceMigrationV2FieldActionsArgs): WorkspaceMigrationFieldActionV2[] => {
let allUpdatedObjectMetadataFieldActions: WorkspaceMigrationFieldActionV2[] =
[];
@@ -53,12 +58,14 @@ export const buildWorkspaceMigrationV2FieldActions = (
}),
);
const deleteFieldAction = deletedFieldMetadata.map((flatFieldMetadata) =>
getWorkspaceMigrationV2FieldDeleteAction({
flatFieldMetadata,
flatObjectMetadata,
}),
);
const deleteFieldAction = inferDeletionFromMissingObjectFieldIndex
? deletedFieldMetadata.map((flatFieldMetadata) =>
getWorkspaceMigrationV2FieldDeleteAction({
flatFieldMetadata,
flatObjectMetadata,
}),
)
: [];
allUpdatedObjectMetadataFieldActions =
allUpdatedObjectMetadataFieldActions.concat([
@@ -6,9 +6,14 @@ import {
getWorkspaceMigrationV2DeleteIndexAction,
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-index-actions';
export const buildWorkspaceMigrationIndexActions = (
objectMetadataDeletedCreatedUpdatedIndex: UpdatedObjectMetadataDeletedCreatedUpdatedIndexMatrix[],
): WorkspaceMigrationIndexActionV2[] => {
type BuildWorkspaceMigrationIndexActionsArgs = {
objectMetadataDeletedCreatedUpdatedIndex: UpdatedObjectMetadataDeletedCreatedUpdatedIndexMatrix[];
inferDeletionFromMissingObjectFieldIndex: boolean;
};
export const buildWorkspaceMigrationIndexActions = ({
inferDeletionFromMissingObjectFieldIndex,
objectMetadataDeletedCreatedUpdatedIndex,
}: BuildWorkspaceMigrationIndexActionsArgs): WorkspaceMigrationIndexActionV2[] => {
let allUpdatedObjectMetadataIndexActions: WorkspaceMigrationIndexActionV2[] =
[];
@@ -36,9 +41,9 @@ export const buildWorkspaceMigrationIndexActions = (
const createIndexActions = createdIndexMetadata.map(
getWorkspaceMigrationV2CreateIndexAction,
);
const deleteIndexActions = deletedIndexMetadata.map(
getWorkspaceMigrationV2DeleteIndexAction,
);
const deleteIndexActions = inferDeletionFromMissingObjectFieldIndex
? deletedIndexMetadata.map(getWorkspaceMigrationV2DeleteIndexAction)
: [];
allUpdatedObjectMetadataIndexActions =
allUpdatedObjectMetadataIndexActions.concat([