Fix flat field metadata date type (#16445)

# Introduction
Following https://github.com/twentyhq/twenty/pull/16420
This commit is contained in:
Paul Rastoin
2025-12-09 19:53:36 +01:00
committed by GitHub
parent 83fc434c5d
commit 7b98804ec1
22 changed files with 75 additions and 90 deletions
@@ -33,7 +33,7 @@ export class ComputeTwentyStandardWorkspaceMigrationCommand extends CommandRunne
const twentyStandardApplicationId = '20202020-5adb-4091-81b7-d5be86a8bdd2';
const twentyStandardAllFlatEntityMaps =
computeTwentyStandardApplicationAllFlatEntityMaps({
now: new Date(),
now: new Date().toISOString(),
workspaceId,
twentyStandardApplicationId,
});
@@ -0,0 +1,9 @@
export type CastRecordTypeOrmDatePropertiesToString<T> = {
[P in keyof T as [T[P]] extends [never]
? never
: [NonNullable<T[P]>] extends [never]
? never
: NonNullable<T[P]> extends Date
? P
: never]: null extends T[P] ? string | null : string;
};
@@ -1,7 +1,6 @@
import { type SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface';
import { type ExtractRecordTypeOrmNonNullableDateProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-non-nullable-date-properties.type';
import { type ExtractRecordTypeOrmNullableDateProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-nullable-date-properties.type';
import { type CastRecordTypeOrmDatePropertiesToString } from 'src/engine/metadata-modules/flat-entity/types/cast-record-typeorm-date-properties-to-string.type';
import { type NonNullableProperties } from 'src/types/non-nullable-properties.type';
export type SyncableFlatEntity = NonNullableProperties<
@@ -11,23 +10,13 @@ export type SyncableFlatEntity = NonNullableProperties<
applicationId: string | null;
};
export type EntityNullableDateProperties<TEntity> =
ExtractRecordTypeOrmNullableDateProperties<TEntity>;
export type EntityNonNullableDateProperties<TEntity> =
ExtractRecordTypeOrmNonNullableDateProperties<TEntity>;
export type FlatEntityFrom<
TEntity,
TEntityRelationProperties extends keyof TEntity,
> = Omit<
TEntity,
| TEntityRelationProperties
| EntityNonNullableDateProperties<TEntity>
| EntityNullableDateProperties<TEntity>
| 'application'
> & {
[P in EntityNonNullableDateProperties<TEntity>]: string;
} & {
[P in EntityNullableDateProperties<TEntity>]: string | null;
};
| keyof CastRecordTypeOrmDatePropertiesToString<TEntity>
> &
CastRecordTypeOrmDatePropertiesToString<TEntity>;
@@ -6,17 +6,14 @@ import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-m
type FlatFieldMetadataOverrides<
T extends FieldMetadataType = FieldMetadataType,
> = Required<
Pick<
FlatFieldMetadata<T>,
'universalIdentifier' | 'objectMetadataId' | 'type'
>
Pick<FlatFieldMetadata, 'universalIdentifier' | 'objectMetadataId' | 'type'>
> &
Partial<FlatFieldMetadata<T>>;
export const getFlatFieldMetadataMock = <T extends FieldMetadataType>(
overrides: FlatFieldMetadataOverrides<T>,
): FlatFieldMetadata => {
const createdAt = '2024-01-01T00:00:00.000Z' as unknown as Date;
const createdAt = '2024-01-01T00:00:00.000Z';
return {
calendarViewIds: [],
@@ -29,7 +29,7 @@ export const getRelationTargetFlatFieldMetadataMock = ({
relationTargetObjectMetadataId,
...overrides
}: GetMorphOrRelationFlatFieldMetadataMockArgs): FlatFieldMetadata<MorphOrRelationFieldMetadataType> => {
const createdAt = '2024-01-01T00:00:00.000Z' as unknown as Date;
const createdAt = '2024-01-01T00:00:00.000Z';
return {
calendarViewIds: [],
@@ -118,7 +118,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
{
"applicationId": Any<String>,
"calendarViewIds": [],
"createdAt": Any<ClockDate>,
"createdAt": Any<String>,
"defaultValue": null,
"description": "new field description",
"icon": "IconRelationOneToMany",
@@ -146,7 +146,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
"standardOverrides": null,
"type": "MORPH_RELATION",
"universalIdentifier": Any<String>,
"updatedAt": Any<ClockDate>,
"updatedAt": Any<String>,
"viewFieldIds": [],
"viewFilterIds": [],
"workspaceId": Any<String>,
@@ -154,7 +154,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
{
"applicationId": Any<String>,
"calendarViewIds": [],
"createdAt": Any<ClockDate>,
"createdAt": Any<String>,
"defaultValue": null,
"description": null,
"icon": "IconPet",
@@ -184,7 +184,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
"standardOverrides": null,
"type": "RELATION",
"universalIdentifier": Any<String>,
"updatedAt": Any<ClockDate>,
"updatedAt": Any<String>,
"viewFieldIds": [],
"viewFilterIds": [],
"workspaceId": Any<String>,
@@ -192,7 +192,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
{
"applicationId": Any<String>,
"calendarViewIds": [],
"createdAt": Any<ClockDate>,
"createdAt": Any<String>,
"defaultValue": null,
"description": "new field description",
"icon": "IconRelationOneToMany",
@@ -220,7 +220,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
"standardOverrides": null,
"type": "MORPH_RELATION",
"universalIdentifier": Any<String>,
"updatedAt": Any<ClockDate>,
"updatedAt": Any<String>,
"viewFieldIds": [],
"viewFilterIds": [],
"workspaceId": Any<String>,
@@ -228,7 +228,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
{
"applicationId": Any<String>,
"calendarViewIds": [],
"createdAt": Any<ClockDate>,
"createdAt": Any<String>,
"defaultValue": null,
"description": null,
"icon": "IconBuilding",
@@ -258,7 +258,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
"standardOverrides": null,
"type": "RELATION",
"universalIdentifier": Any<String>,
"updatedAt": Any<ClockDate>,
"updatedAt": Any<String>,
"viewFieldIds": [],
"viewFilterIds": [],
"workspaceId": Any<String>,
@@ -1,6 +1,7 @@
import { type FieldMetadataType } from 'twenty-shared/types';
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
export const FIELD_METADATA_RELATION_PROPERTIES = [
'relationTargetFieldMetadata',
@@ -14,15 +15,16 @@ export const FIELD_METADATA_RELATION_PROPERTIES = [
'kanbanAggregateOperationViews',
'calendarViews',
'mainGroupByFieldMetadataViews',
'viewGroups',
] as const satisfies (keyof FieldMetadataEntity)[];
export type FieldMetadataEntityRelationProperties =
(typeof FIELD_METADATA_RELATION_PROPERTIES)[number];
export type FlatFieldMetadata<T extends FieldMetadataType = FieldMetadataType> =
Omit<
FlatEntityFrom<
FieldMetadataEntity<T>,
FieldMetadataEntityRelationProperties | 'viewGroups'
FieldMetadataEntityRelationProperties
> & {
universalIdentifier: string;
viewFieldIds: string[];
@@ -20,6 +20,8 @@ export const fromFieldMetadataEntityToFlatFieldMetadata = <
return {
...fieldMetadataWithoutRelations,
createdAt: fieldMetadataWithoutRelations.createdAt.toISOString(),
updatedAt: fieldMetadataWithoutRelations.updatedAt.toISOString(),
kanbanAggregateOperationViewIds:
fieldMetadataEntity.kanbanAggregateOperationViews.map(({ id }) => id),
calendarViewIds: fieldMetadataEntity.calendarViews.map(({ id }) => id),
@@ -22,7 +22,7 @@ export const getDefaultFlatFieldMetadata = ({
['defaultValue', 'settings'],
);
const createdAt = new Date();
const createdAt = new Date().toISOString();
return {
calendarViewIds: [],
@@ -197,8 +197,8 @@ const validateDuplicates = (
return errors;
};
const validateFieldMetadataInputOptions = <T extends EnumFieldMetadataType>(
flatFieldMetadata: FlatFieldMetadata<T>,
const validateFieldMetadataInputOptions = (
flatFieldMetadata: FlatFieldMetadata<EnumFieldMetadataType>,
): FlatFieldMetadataValidationError[] => {
const { options } = flatFieldMetadata;
@@ -22,7 +22,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
workspaceId,
flatObjectMetadata: { id: objectMetadataId, applicationId },
}: BuildDefaultFlatFieldMetadataForCustomObjectArgs) => {
const createdAt = new Date();
const createdAt = new Date().toISOString();
const idFieldId = v4();
const idField: FlatFieldMetadata<FieldMetadataType.UUID> = {
type: FieldMetadataType.UUID,
@@ -51,7 +51,7 @@ const generateSourceFlatFieldMetadata = ({
);
}
const createdAt = new Date();
const createdAt = new Date().toISOString();
const sourceFieldMetadataId = v4();
const targetFieldMetadataId = v4();
const icon =
@@ -119,7 +119,7 @@ const generateTargetFlatFieldMetadata = ({
relationObjectMetadataNamePlural: targetFlatObjectMetadata.namePlural,
targetObjectLabelSingular: sourceFlatObjectMetadata.labelSingular,
});
const createdAt = new Date();
const createdAt = new Date().toISOString();
const standardId = createRelationDeterministicUuid({
objectId: sourceFlatObjectMetadata.id,
standardId: customStandardFieldId,
@@ -130,8 +130,8 @@ describe('WorkspaceEntityManager', () => {
objectMetadataId: 'test-entity-id',
isNullable: true,
isLabelSyncedWithName: false,
createdAt: new Date(),
updatedAt: new Date(),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
universalIdentifier: 'field-id',
defaultValue: null,
description: null,
@@ -78,8 +78,8 @@ describe('WorkspaceRepository', () => {
icon: 'IconKey',
workspaceId: 'test-workspace-id',
universalIdentifier: 'id-field-universal-id',
createdAt: new Date(),
updatedAt: new Date(),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
defaultValue: null,
options: null,
settings: null,
@@ -78,7 +78,7 @@ export const createStandardIndexFlatMetadata = <
return generateFlatIndexMetadataWithNameOrThrow({
flatIndex: {
createdAt: now.toISOString(),
createdAt: now,
applicationId: twentyStandardApplicationId,
indexType,
indexWhereClause,
@@ -86,17 +86,17 @@ export const createStandardIndexFlatMetadata = <
isUnique,
objectMetadataId,
universalIdentifier: indexDefinition.universalIdentifier,
updatedAt: now.toISOString(),
updatedAt: now,
workspaceId,
id: indexId,
flatIndexFieldMetadatas: flatFieldMetadatas.map<FlatIndexFieldMetadata>(
({ id: fieldMetadataId }, index) => ({
createdAt: now.toISOString(),
createdAt: now,
fieldMetadataId,
id: v4(),
indexMetadataId: indexId,
order: index,
updatedAt: now.toISOString(),
updatedAt: now,
}),
),
},
@@ -81,7 +81,7 @@ export const createStandardObjectFlatMetadata = <
fieldMetadataIds: [],
indexMetadataIds: [],
viewIds: [],
createdAt: now.toISOString(),
updatedAt: now.toISOString(),
createdAt: now,
updatedAt: now,
id: standardFieldMetadataIdByObjectAndFieldName[nameSingular].id,
});
@@ -6,7 +6,7 @@ import { buildStandardFlatIndexMetadataMaps } from 'src/engine/workspace-manager
import { buildStandardFlatObjectMetadataMaps } from 'src/engine/workspace-manager/twenty-standard-application/utils/object-metadata/build-standard-flat-object-metadata-maps.util';
export type ComputeTwentyStandardApplicationAllFlatEntityMapsArgs = {
now: Date;
now: string;
workspaceId: string;
twentyStandardApplicationId: string;
};
@@ -1,5 +0,0 @@
export type ExtractRecordTypeOrmNonNullableDateProperties<T> = NonNullable<
{
[P in keyof T]: null extends T[P] ? never : T[P] extends Date ? P : never;
}[keyof T]
>;
@@ -1,9 +0,0 @@
export type ExtractRecordTypeOrmNullableDateProperties<T> = NonNullable<
{
[P in keyof T]: null extends T[P]
? NonNullable<T[P]> extends Date
? P
: never
: never;
}[keyof T]
>;
@@ -7,7 +7,7 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a crea
"field-id-1": {
"applicationId": "application-id-1",
"calendarViewIds": [],
"createdAt": 2024-01-01T00:00:00.000Z,
"createdAt": "2024-01-01T00:00:00.000Z",
"defaultValue": null,
"description": "default flat field metadata description",
"icon": "icon",
@@ -33,7 +33,7 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a crea
"standardOverrides": null,
"type": "TEXT",
"universalIdentifier": "universal-identifier-1",
"updatedAt": 2024-01-01T00:00:00.000Z,
"updatedAt": "2024-01-01T00:00:00.000Z",
"viewFieldIds": [],
"viewFilterIds": [],
"workspaceId": "workspace-id-1",
@@ -71,7 +71,7 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a dele
"field-id-1": {
"applicationId": "application-id-1",
"calendarViewIds": [],
"createdAt": 2024-01-01T00:00:00.000Z,
"createdAt": "2024-01-01T00:00:00.000Z",
"defaultValue": null,
"description": "default flat field metadata description",
"icon": "icon",
@@ -97,7 +97,7 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a dele
"standardOverrides": null,
"type": "TEXT",
"universalIdentifier": "universal-identifier-1",
"updatedAt": 2024-01-01T00:00:00.000Z,
"updatedAt": "2024-01-01T00:00:00.000Z",
"viewFieldIds": [],
"viewFilterIds": [],
"workspaceId": "workspace-id-1",
@@ -153,7 +153,7 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect create
"field-id-3": {
"applicationId": "application-id-1",
"calendarViewIds": [],
"createdAt": 2024-01-01T00:00:00.000Z,
"createdAt": "2024-01-01T00:00:00.000Z",
"defaultValue": null,
"description": "default flat field metadata description",
"icon": "icon",
@@ -179,7 +179,7 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect create
"standardOverrides": null,
"type": "TEXT",
"universalIdentifier": "universal-identifier-3",
"updatedAt": 2024-01-01T00:00:00.000Z,
"updatedAt": "2024-01-01T00:00:00.000Z",
"viewFieldIds": [],
"viewFilterIds": [],
"workspaceId": "workspace-id-1",
@@ -199,7 +199,7 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect create
"field-id-2": {
"applicationId": "application-id-1",
"calendarViewIds": [],
"createdAt": 2024-01-01T00:00:00.000Z,
"createdAt": "2024-01-01T00:00:00.000Z",
"defaultValue": null,
"description": "default flat field metadata description",
"icon": "icon",
@@ -225,7 +225,7 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect create
"standardOverrides": null,
"type": "TEXT",
"universalIdentifier": "universal-identifier-2",
"updatedAt": 2024-01-01T00:00:00.000Z,
"updatedAt": "2024-01-01T00:00:00.000Z",
"viewFieldIds": [],
"viewFilterIds": [],
"workspaceId": "workspace-id-1",
@@ -28,8 +28,8 @@ describe('flatEntityDeletedCreatedUpdatedMatrixDispatcher', () => {
id: 'field-id-1',
workspaceId: 'workspace-id-1',
applicationId: 'application-id-1',
createdAt: new Date('2024-01-01T00:00:00.000Z'),
updatedAt: new Date('2024-01-01T00:00:00.000Z'),
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z',
}),
],
metadataName: 'fieldMetadata',
@@ -50,8 +50,8 @@ describe('flatEntityDeletedCreatedUpdatedMatrixDispatcher', () => {
id: 'field-id-1',
workspaceId: 'workspace-id-1',
applicationId: 'application-id-1',
createdAt: new Date('2024-01-01T00:00:00.000Z'),
updatedAt: new Date('2024-01-01T00:00:00.000Z'),
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z',
}),
],
to: [],
@@ -73,8 +73,8 @@ describe('flatEntityDeletedCreatedUpdatedMatrixDispatcher', () => {
id: 'field-id-1',
workspaceId: 'workspace-id-1',
applicationId: 'application-id-1',
createdAt: new Date('2024-01-01T00:00:00.000Z'),
updatedAt: new Date('2024-01-01T00:00:00.000Z'),
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z',
isActive: false,
}),
],
@@ -86,8 +86,8 @@ describe('flatEntityDeletedCreatedUpdatedMatrixDispatcher', () => {
id: 'field-id-1',
workspaceId: 'workspace-id-1',
applicationId: 'application-id-1',
createdAt: new Date('2024-01-01T00:00:00.000Z'),
updatedAt: new Date('2024-01-01T00:00:00.000Z'),
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z',
isActive: true,
}),
],
@@ -109,8 +109,8 @@ describe('flatEntityDeletedCreatedUpdatedMatrixDispatcher', () => {
id: 'field-id-1',
workspaceId: 'workspace-id-1',
applicationId: 'application-id-1',
createdAt: new Date('2024-01-01T00:00:00.000Z'),
updatedAt: new Date('2024-01-01T00:00:00.000Z'),
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z',
isActive: true,
}),
getFlatFieldMetadataMock({
@@ -120,8 +120,8 @@ describe('flatEntityDeletedCreatedUpdatedMatrixDispatcher', () => {
id: 'field-id-2',
workspaceId: 'workspace-id-1',
applicationId: 'application-id-1',
createdAt: new Date('2024-01-01T00:00:00.000Z'),
updatedAt: new Date('2024-01-01T00:00:00.000Z'),
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z',
}),
],
to: [
@@ -132,8 +132,8 @@ describe('flatEntityDeletedCreatedUpdatedMatrixDispatcher', () => {
id: 'field-id-1',
workspaceId: 'workspace-id-1',
applicationId: 'application-id-1',
createdAt: new Date('2024-01-01T00:00:00.000Z'),
updatedAt: new Date('2024-01-01T00:00:00.000Z'),
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z',
isActive: false,
}),
getFlatFieldMetadataMock({
@@ -143,8 +143,8 @@ describe('flatEntityDeletedCreatedUpdatedMatrixDispatcher', () => {
id: 'field-id-3',
workspaceId: 'workspace-id-1',
applicationId: 'application-id-1',
createdAt: new Date('2024-01-01T00:00:00.000Z'),
updatedAt: new Date('2024-01-01T00:00:00.000Z'),
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z',
}),
],
metadataName: 'fieldMetadata',
@@ -166,8 +166,8 @@ describe('flatEntityDeletedCreatedUpdatedMatrixDispatcher', () => {
id: 'field-id-1',
workspaceId: 'workspace-id-1',
applicationId: 'application-id-1',
createdAt: new Date('2024-01-01T00:00:00.000Z'),
updatedAt: new Date('2024-01-01T00:00:00.000Z'),
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z',
}),
],
to: [],
@@ -52,7 +52,7 @@ type UpdateFieldPropertyUpdateHandlerArgs<
schemaName: string;
tableName: string;
flatFieldMetadata: FlatFieldMetadata<T>;
update: PropertyUpdate<FlatFieldMetadata<T>, P>;
update: PropertyUpdate<FlatFieldMetadata, P>;
};
@Injectable()