[REQUIRES_CACHE_FLUSH_FOR_FIELD_AND_OBJECT]FlatFieldMetadata and FlatObjectMetadata required universal (#17557)

# Introduction
In this PR we're migrating both the `field` and `object` metadata to be
using the new `FlatEntityFromV2` that requires all the
`UniversalFlatEntityExtraProperties` to be spread at the flat entity
root.

This means that we have to update all of their flat declaration

This type swap allows to isole a specific entity migration into his own
type scope and avoid to have everything handled at once

```ts
/**
 * Currently under migration but aims to replace FlatEntity afterwards
 */
export type FlatEntityFromV2<
  TEntity,
  TMetadataName extends AllMetadataName | undefined = undefined,
  TInnerFlatEntity extends { __universal?: unknown } = FlatEntityFrom<
    TEntity,
    TMetadataName
  >,
> = Omit<TInnerFlatEntity, '__universal'> & TInnerFlatEntity['__universal'];

```

## Impact
Both object and field:
- Create input transpilation utils
- from entity to flat tools
- mocks

## Note
Removed from the universal extra properties the jsonb properties that do
not contain a serialized

## Next
Next step is to incrementally make the builder and runner expect
`UniversalFlatEntity` for both of these metadata
This way we will be able to fully migrate an entity e2e typesafely
This commit is contained in:
Paul Rastoin
2026-01-29 19:11:19 +01:00
committed by GitHub
parent e91457a47e
commit fbbd8fe967
69 changed files with 1244 additions and 498 deletions
@@ -100,5 +100,16 @@ export const createStandardFieldFlatMetadata = <
mainGroupByFieldMetadataViewIds: [],
createdAt: now,
updatedAt: now,
applicationUniversalIdentifier: twentyStandardApplicationId,
objectMetadataUniversalIdentifier:
STANDARD_OBJECTS[objectName].universalIdentifier,
relationTargetObjectMetadataUniversalIdentifier: null,
relationTargetFieldMetadataUniversalIdentifier: null,
viewFilterUniversalIdentifiers: [],
viewFieldUniversalIdentifiers: [],
kanbanAggregateOperationViewUniversalIdentifiers: [],
calendarViewUniversalIdentifiers: [],
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
universalSettings: null,
};
};
@@ -83,6 +83,10 @@ export const createStandardRelationFieldFlatMetadata = <
const targetFieldIds =
standardObjectMetadataRelatedEntityIds[targetObjectName].fields;
const targetObjectFields = STANDARD_OBJECTS[targetObjectName].fields;
const targetFieldDefinition =
targetObjectFields[targetFieldName as keyof typeof targetObjectFields];
return {
id: fieldIds[fieldName as keyof typeof fieldIds].id,
universalIdentifier: fieldDefinition.universalIdentifier,
@@ -117,5 +121,18 @@ export const createStandardRelationFieldFlatMetadata = <
mainGroupByFieldMetadataViewIds: [],
createdAt: now,
updatedAt: now,
applicationUniversalIdentifier: twentyStandardApplicationId,
objectMetadataUniversalIdentifier:
STANDARD_OBJECTS[objectName].universalIdentifier,
relationTargetObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS[targetObjectName].universalIdentifier,
relationTargetFieldMetadataUniversalIdentifier:
targetFieldDefinition.universalIdentifier,
viewFilterUniversalIdentifiers: [],
viewFieldUniversalIdentifiers: [],
kanbanAggregateOperationViewUniversalIdentifiers: [],
calendarViewUniversalIdentifiers: [],
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
universalSettings: null,
};
};
@@ -1,4 +1,5 @@
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant';
import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type';
import { type AllStandardObjectName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type';
import { type StandardBuilderArgs } from 'src/engine/workspace-manager/twenty-standard-application/types/metadata-standard-buillder-args.type';
@@ -52,42 +53,56 @@ export const createStandardObjectFlatMetadata = <
standardObjectMetadataRelatedEntityIds,
twentyStandardApplicationId,
now,
}: CreateStandardObjectArgs<O>): FlatObjectMetadata => ({
universalIdentifier,
standardId: universalIdentifier,
applicationId: twentyStandardApplicationId,
workspaceId,
nameSingular,
namePlural,
labelSingular,
labelPlural,
description,
icon,
isCustom: false,
isRemote: false,
isActive: true,
isSystem,
isSearchable,
isAuditLogged,
isUIReadOnly,
isLabelSyncedWithName: false,
standardOverrides: null,
duplicateCriteria,
shortcut,
labelIdentifierFieldMetadataId:
standardObjectMetadataRelatedEntityIds[nameSingular].fields[
}: CreateStandardObjectArgs<O>): FlatObjectMetadata => {
const labelIdentifierFieldMetadataUniversalIdentifier =
// @ts-expect-error ignore
STANDARD_OBJECTS[nameSingular as keyof typeof STANDARD_OBJECTS].fields[
labelIdentifierFieldMetadataName
].id,
imageIdentifierFieldMetadataId: imageIdentifierFieldMetadataName
? standardObjectMetadataRelatedEntityIds[nameSingular].fields[
imageIdentifierFieldMetadataName
].id
: null,
targetTableName: 'DEPRECATED',
fieldIds: [],
indexMetadataIds: [],
viewIds: [],
createdAt: now,
updatedAt: now,
id: standardObjectMetadataRelatedEntityIds[nameSingular].id,
});
].universalIdentifier;
return {
universalIdentifier,
standardId: universalIdentifier,
applicationId: twentyStandardApplicationId,
workspaceId,
nameSingular,
namePlural,
labelSingular,
labelPlural,
description,
icon,
isCustom: false,
isRemote: false,
isActive: true,
isSystem,
isSearchable,
isAuditLogged,
isUIReadOnly,
isLabelSyncedWithName: false,
standardOverrides: null,
duplicateCriteria,
shortcut,
labelIdentifierFieldMetadataId:
standardObjectMetadataRelatedEntityIds[nameSingular].fields[
labelIdentifierFieldMetadataName
].id,
imageIdentifierFieldMetadataId: imageIdentifierFieldMetadataName
? standardObjectMetadataRelatedEntityIds[nameSingular].fields[
imageIdentifierFieldMetadataName
].id
: null,
targetTableName: 'DEPRECATED',
fieldIds: [],
indexMetadataIds: [],
viewIds: [],
createdAt: now,
updatedAt: now,
id: standardObjectMetadataRelatedEntityIds[nameSingular].id,
applicationUniversalIdentifier: twentyStandardApplicationId,
fieldUniversalIdentifiers: [],
viewUniversalIdentifiers: [],
indexMetadataUniversalIdentifiers: [],
labelIdentifierFieldMetadataUniversalIdentifier,
imageIdentifierFieldMetadataUniversalIdentifier: null,
};
};