Fix flat entity maps date serialization (#16420)

Changes:
- as we store date in redis as serialized, let's make all flatEntity
dates as string. This requires changing FlatEntity types and making sure
that entity are converted to flatEntity and flatEntity to dtos
This commit is contained in:
Charles Bochet
2025-12-09 16:41:50 +01:00
committed by GitHub
parent 608e5751a9
commit a18203934c
94 changed files with 357 additions and 204 deletions
@@ -162,8 +162,8 @@ export const mockPersonFlatObjectMetadata = (
viewIds: [],
applicationId: null,
isLabelSyncedWithName: false,
createdAt: new Date(),
updatedAt: new Date(),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
shortcut: null,
description: null,
standardOverrides: null,
@@ -1,7 +1,7 @@
import { objectRecordChangedValues } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-values';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
import { objectRecordChangedValues } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-values';
const mockObjectMetadata = {
id: '1',
@@ -24,8 +24,8 @@ const mockObjectMetadata = {
viewIds: [],
applicationId: null,
isLabelSyncedWithName: false,
createdAt: new Date(),
updatedAt: new Date(),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
shortcut: null,
description: null,
standardOverrides: null,
@@ -38,7 +38,7 @@ export const fromCreateAgentInputToFlatAgent = ({
],
);
const createdAt = new Date();
const createdAt = new Date().toISOString();
const agentId = v4();
const standardId = createAgentInput.standardId ?? null;
const universalIdentifier = standardId ?? agentId;
@@ -38,7 +38,7 @@ const computeAgentFlatRoleTargetToUpdate = ({
}
const existingRoleTarget = flatRoleTargetByAgentIdMaps[flatAgent.id];
const updatedAt = new Date();
const updatedAt = new Date().toISOString();
if (roleId === null) {
if (isDefined(existingRoleTarget)) {
@@ -46,6 +46,8 @@ export class WorkspaceFlatCronTriggerMapCacheService extends WorkspaceCacheProvi
]),
universalIdentifier:
cronTriggerEntity.universalIdentifier ?? cronTriggerEntity.id,
createdAt: cronTriggerEntity.createdAt.toISOString(),
updatedAt: cronTriggerEntity.updatedAt.toISOString(),
} satisfies FlatCronTrigger;
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
@@ -12,7 +12,7 @@ export const fromCreateCronTriggerInputToFlatCronTrigger = ({
workspaceId: string;
workspaceCustomApplicationId: string;
}): FlatCronTrigger => {
const now = new Date();
const now = new Date().toISOString();
const id = v4();
return {
@@ -26,6 +26,6 @@ export const fromUpdateCronTriggerInputToFlatCronTriggerToUpdateOrThrow = ({
return {
...existingFlatCronTrigger,
settings: updateCronTriggerInput.update.settings,
updatedAt: new Date(),
updatedAt: new Date().toISOString(),
};
};
@@ -48,6 +48,8 @@ export class WorkspaceFlatDatabaseEventTriggerMapCacheService extends WorkspaceC
universalIdentifier:
databaseEventTriggerEntity.universalIdentifier ??
databaseEventTriggerEntity.id,
createdAt: databaseEventTriggerEntity.createdAt.toISOString(),
updatedAt: databaseEventTriggerEntity.updatedAt.toISOString(),
} satisfies FlatDatabaseEventTrigger;
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
@@ -12,7 +12,7 @@ export const fromCreateDatabaseEventTriggerInputToFlatDatabaseEventTrigger = ({
workspaceId: string;
workspaceCustomApplicationId: string;
}): FlatDatabaseEventTrigger => {
const now = new Date();
const now = new Date().toISOString();
const id = uuidV4();
return {
@@ -27,6 +27,6 @@ export const fromUpdateDatabaseEventTriggerInputToFlatDatabaseEventTriggerToUpda
return {
...existingFlatDatabaseEventTrigger,
settings: updateDatabaseEventTriggerInput.update.settings,
updatedAt: new Date(),
updatedAt: new Date().toISOString(),
};
};
@@ -20,7 +20,7 @@ export const fromFlatAgentWithRoleIdToAgentDto = ({
workspaceId,
roleId,
}: FlatAgentWithRoleId): AgentDTO => ({
createdAt,
createdAt: new Date(createdAt),
description: description ?? undefined,
evaluationInputs,
id,
@@ -32,7 +32,7 @@ export const fromFlatAgentWithRoleIdToAgentDto = ({
prompt,
responseFormat,
standardId,
updatedAt,
updatedAt: new Date(updatedAt),
workspaceId,
applicationId: applicationId ?? undefined,
icon: icon ?? undefined,
@@ -5,9 +5,9 @@ export const transformAgentEntityToFlatAgent = (
agentEntity: AgentEntity,
): FlatAgent => {
return {
createdAt: agentEntity.createdAt,
deletedAt: agentEntity.deletedAt,
updatedAt: agentEntity.updatedAt,
createdAt: agentEntity.createdAt.toISOString(),
deletedAt: agentEntity.deletedAt?.toISOString() ?? null,
updatedAt: agentEntity.updatedAt.toISOString(),
id: agentEntity.id,
standardId: agentEntity.standardId,
name: agentEntity.name,
@@ -21,13 +21,13 @@ export const transformStandardAgentDefinitionToFlatAgent = ({
outputStrategy: _outputStrategy,
...agentData
} = standardAgentDefinition;
const createdAt = new Date();
const createdAt = new Date().toISOString();
return {
id: existingAgentEntity?.id ?? v4(),
createdAt: existingAgentEntity?.createdAt ?? createdAt,
updatedAt: existingAgentEntity?.updatedAt ?? createdAt,
deletedAt: existingAgentEntity?.deletedAt ?? null,
createdAt: existingAgentEntity?.createdAt?.toISOString() ?? createdAt,
updatedAt: existingAgentEntity?.updatedAt?.toISOString() ?? createdAt,
deletedAt: existingAgentEntity?.deletedAt?.toISOString() ?? null,
...agentData,
workspaceId,
universalIdentifier: standardAgentDefinition.standardId,
@@ -1,9 +1,9 @@
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
export const createEmptyFlatEntityMaps = () =>
({
byId: {},
idByUniversalIdentifier: {},
universalIdentifiersByApplicationId: {},
}) as const satisfies FlatEntityMaps<FlatEntity>;
}) as const satisfies FlatEntityMaps<SyncableFlatEntity>;
@@ -1,8 +1,8 @@
import { type Expect } from 'twenty-shared/testing';
import { type AllMetadataName } from 'twenty-shared/metadata';
import { type Expect } from 'twenty-shared/testing';
import { type AllFlatEntityTypesByMetadataName } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-types-by-metadata-name';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type WorkspaceMigrationActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2';
type ExpectedGenericFlatEntityInformation = {
@@ -11,7 +11,7 @@ type ExpectedGenericFlatEntityInformation = {
deleted: WorkspaceMigrationActionV2 | WorkspaceMigrationActionV2[];
updated: WorkspaceMigrationActionV2 | WorkspaceMigrationActionV2[];
};
flatEntity: FlatEntity;
flatEntity: SyncableFlatEntity;
};
type ExpectedGenericAllFlatEntityInformationByMetadataEngine = {
@@ -1,6 +1,6 @@
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
export type FlatEntityMaps<T extends FlatEntity> = {
export type FlatEntityMaps<T extends SyncableFlatEntity> = {
byId: Partial<Record<string, T>>;
idByUniversalIdentifier: Partial<Record<string, string>>;
universalIdentifiersByApplicationId: Partial<Record<string, string[]>>;
@@ -1,22 +1,33 @@
import { type SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface';
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type';
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 NonNullableProperties } from 'src/types/non-nullable-properties.type';
export type SyncableEntityRelationProperties =
ExtractRecordTypeOrmRelationProperties<SyncableEntity, ApplicationEntity>;
export interface FlatEntity
extends NonNullableProperties<
Omit<SyncableEntity, SyncableEntityRelationProperties | 'applicationId'>
> {
export type SyncableFlatEntity = NonNullableProperties<
Omit<SyncableEntity, 'application' | 'applicationId'>
> & {
id: string;
applicationId: string | null;
}
};
export type EntityNullableDateProperties<TEntity> =
ExtractRecordTypeOrmNullableDateProperties<TEntity>;
export type EntityNonNullableDateProperties<TEntity> =
ExtractRecordTypeOrmNonNullableDateProperties<TEntity>;
export type FlatEntityFrom<
TEntity extends SyncableEntity,
TEntity,
TEntityRelationProperties extends keyof TEntity,
> = FlatEntity &
Omit<TEntity, TEntityRelationProperties | SyncableEntityRelationProperties>;
> = Omit<
TEntity,
| TEntityRelationProperties
| EntityNonNullableDateProperties<TEntity>
| EntityNullableDateProperties<TEntity>
| 'application'
> & {
[P in EntityNonNullableDateProperties<TEntity>]: string;
} & {
[P in EntityNullableDateProperties<TEntity>]: string | null;
};
@@ -50,8 +50,8 @@ describe('deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThr
viewGroupIds: [],
workspaceId,
calendarFieldMetadataId: mockFieldMetadata.id,
createdAt: new Date('2024-01-01'),
updatedAt: new Date('2024-01-01'),
createdAt: new Date('2024-01-01').toISOString(),
updatedAt: new Date('2024-01-01').toISOString(),
icon: 'icon',
isCompact: false,
name: 'View Name',
@@ -5,14 +5,16 @@ import {
FlatEntityMapsExceptionCode,
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
type AddFlatEntityToFlatEntityMapsOrThrowArgs<T extends FlatEntity> = {
type AddFlatEntityToFlatEntityMapsOrThrowArgs<T extends SyncableFlatEntity> = {
flatEntity: T;
flatEntityMaps: FlatEntityMaps<T>;
};
export const addFlatEntityToFlatEntityMapsOrThrow = <T extends FlatEntity>({
export const addFlatEntityToFlatEntityMapsOrThrow = <
T extends SyncableFlatEntity,
>({
flatEntity,
flatEntityMaps,
}: AddFlatEntityToFlatEntityMapsOrThrowArgs<T>): FlatEntityMaps<T> => {
@@ -6,17 +6,17 @@ import {
FlatEntityMapsExceptionCode,
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
export type DeleteFlatEntityFromFlatEntityMapsOrThrowArgs<
T extends FlatEntity,
T extends SyncableFlatEntity,
> = {
entityToDeleteId: string;
flatEntityMaps: FlatEntityMaps<T>;
};
export const deleteFlatEntityFromFlatEntityMapsOrThrow = <
T extends FlatEntity,
T extends SyncableFlatEntity,
>({
flatEntityMaps,
entityToDeleteId,
@@ -6,16 +6,16 @@ import {
FlatEntityMapsExceptionCode,
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
export type FindFlatEntityByIdInFlatEntityMapsOrThrowArgs<
T extends FlatEntity,
T extends SyncableFlatEntity,
> = {
flatEntityMaps: FlatEntityMaps<T>;
flatEntityId: string;
};
export const findFlatEntityByIdInFlatEntityMapsOrThrow = <
T extends FlatEntity,
T extends SyncableFlatEntity,
>({
flatEntityMaps,
flatEntityId,
@@ -1,10 +1,12 @@
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import {
findFlatEntityByIdInFlatEntityMapsOrThrow,
type FindFlatEntityByIdInFlatEntityMapsOrThrowArgs,
} from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
export const findFlatEntityByIdInFlatEntityMaps = <T extends FlatEntity>(
export const findFlatEntityByIdInFlatEntityMaps = <
T extends SyncableFlatEntity,
>(
args: FindFlatEntityByIdInFlatEntityMapsOrThrowArgs<T>,
): T | undefined => {
try {
@@ -1,17 +1,17 @@
import { isDefined } from 'twenty-shared/utils';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { getSubFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-maps-or-throw.util';
export type FindManyFlatEntityByIdInFlatEntityMapsOrThrowArgs<
T extends FlatEntity,
T extends SyncableFlatEntity,
> = {
flatEntityMaps: FlatEntityMaps<T>;
flatEntityIds: string[];
};
export const findManyFlatEntityByIdInFlatEntityMapsOrThrow = <
T extends FlatEntity,
T extends SyncableFlatEntity,
>({
flatEntityMaps,
flatEntityIds,
@@ -1,9 +1,9 @@
import { isDefined } from 'twenty-shared/utils';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
export const getFlatEntitiesByApplicationId = <T extends FlatEntity>(
export const getFlatEntitiesByApplicationId = <T extends SyncableFlatEntity>(
maps: FlatEntityMaps<T>,
applicationId: string,
): T[] => {
@@ -1,9 +1,11 @@
import { isDefined } from 'twenty-shared/utils';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
export const getFlatEntityByUniversalIdentifier = <T extends FlatEntity>(
export const getFlatEntityByUniversalIdentifier = <
T extends SyncableFlatEntity,
>(
maps: FlatEntityMaps<T>,
universalIdentifier: string,
): T | undefined => {
@@ -1,10 +1,10 @@
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
export const getSubFlatEntityMapsOrThrow = <T extends FlatEntity>({
export const getSubFlatEntityMapsOrThrow = <T extends SyncableFlatEntity>({
flatEntityIds,
flatEntityMaps,
}: {
@@ -1,15 +1,18 @@
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
export type ReplaceFlatEntityInFlatEntityMapsOrThrowArgs<T extends FlatEntity> =
{
flatEntity: T;
flatEntityMaps: FlatEntityMaps<T>;
};
export type ReplaceFlatEntityInFlatEntityMapsOrThrowArgs<
T extends SyncableFlatEntity,
> = {
flatEntity: T;
flatEntityMaps: FlatEntityMaps<T>;
};
export const replaceFlatEntityInFlatEntityMapsOrThrow = <T extends FlatEntity>({
export const replaceFlatEntityInFlatEntityMapsOrThrow = <
T extends SyncableFlatEntity,
>({
flatEntity,
flatEntityMaps,
}: ReplaceFlatEntityInFlatEntityMapsOrThrowArgs<T>): FlatEntityMaps<T> => {
@@ -1,8 +1,8 @@
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { orderObjectProperties } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/order-object-properties.util';
export function transformFlatEntityForComparison<
TFlatEntity extends FlatEntity,
TFlatEntity extends SyncableFlatEntity,
PToCompare extends keyof TFlatEntity,
PJsonB extends PToCompare,
>({
@@ -267,15 +267,15 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
"indexMetadatas": [
{
"applicationId": Any<String>,
"createdAt": Any<ClockDate>,
"createdAt": Any<String>,
"flatIndexFieldMetadatas": [
{
"createdAt": Any<ClockDate>,
"createdAt": Any<String>,
"fieldMetadataId": Any<String>,
"id": Any<String>,
"indexMetadataId": Any<String>,
"order": 0,
"updatedAt": Any<ClockDate>,
"updatedAt": Any<String>,
},
],
"id": Any<String>,
@@ -286,20 +286,20 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
"name": "IDX_f687e4e4252800dddd8e5518362",
"objectMetadataId": Any<String>,
"universalIdentifier": Any<String>,
"updatedAt": Any<ClockDate>,
"updatedAt": Any<String>,
"workspaceId": Any<String>,
},
{
"applicationId": Any<String>,
"createdAt": Any<ClockDate>,
"createdAt": Any<String>,
"flatIndexFieldMetadatas": [
{
"createdAt": Any<ClockDate>,
"createdAt": Any<String>,
"fieldMetadataId": Any<String>,
"id": Any<String>,
"indexMetadataId": Any<String>,
"order": 0,
"updatedAt": Any<ClockDate>,
"updatedAt": Any<String>,
},
],
"id": Any<String>,
@@ -310,7 +310,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
"name": "IDX_cb15d901e889e25d0a9acecb595",
"objectMetadataId": Any<String>,
"universalIdentifier": Any<String>,
"updatedAt": Any<ClockDate>,
"updatedAt": Any<String>,
"workspaceId": Any<String>,
},
],
@@ -18,7 +18,7 @@ export const generateIndexForFlatFieldMetadata = ({
workspaceId,
}: GenerateIndexForFlatFieldMetadataArgs): FlatIndexMetadata => {
const indexId = v4();
const createdAt = new Date();
const createdAt = new Date().toISOString();
const flatIndex: FlatIndexMetadata = generateFlatIndexMetadataWithNameOrThrow(
{
@@ -65,7 +65,7 @@ export const recomputeViewGroupsOnEnumFlatFieldMetadataIsNullableUpdate = ({
) {
const highestViewGroupPosition = highestViewGroupPositionByViewId[viewId];
const viewGroupId = v4();
const createdAt = new Date();
const createdAt = new Date().toISOString();
sideEffectResult.flatViewGroupsToCreate.push({
id: viewGroupId,
@@ -89,7 +89,7 @@ export const recomputeViewGroupsOnFlatFieldMetadataOptionsUpdate = ({
const viewIds = Object.keys(viewGroupsByViewId.flatViewGroupRecordByViewId);
const createdAt = new Date();
const createdAt = new Date().toISOString();
const flatViewGroupsToCreate = createdFieldMetadataOptions.flatMap(
(option, createdOptionIndex) =>
viewIds.map<FlatViewGroup>((viewId) => {
@@ -10,7 +10,7 @@ type FlatIndexMetadataOverrides = Required<
export const getFlatIndexMetadataMock = (
overrides: FlatIndexMetadataOverrides,
): FlatIndexMetadata => {
const createdAt = faker.date.anytime();
const createdAt = faker.date.anytime().toISOString();
return {
flatIndexFieldMetadatas: [],
@@ -10,13 +10,15 @@ export type IndexMetadataRelationProperties =
MetadataEntitiesRelationTarget
>;
// Can't use FlatEntityFrom here because IndexFieldMetadataEntity is not a SyncableEntity
export type FlatIndexFieldMetadata = Omit<
IndexFieldMetadataEntity,
export type IndexFieldMetadataEntityRelationProperties =
ExtractRecordTypeOrmRelationProperties<
IndexFieldMetadataEntity,
MetadataEntitiesRelationTarget
>
>;
export type FlatIndexFieldMetadata = FlatEntityFrom<
IndexFieldMetadataEntity,
IndexFieldMetadataEntityRelationProperties
>;
export type FlatIndexMetadata = FlatEntityFrom<
@@ -14,15 +14,20 @@ export const fromIndexMetadataEntityToFlatIndexMetadata = (
return {
...indexMetadataEntityWithoutRelations,
createdAt: indexMetadataEntity.createdAt.toISOString(),
updatedAt: indexMetadataEntity.updatedAt.toISOString(),
universalIdentifier:
indexMetadataEntityWithoutRelations.universalIdentifier ??
indexMetadataEntityWithoutRelations.id,
flatIndexFieldMetadatas: indexMetadataEntity.indexFieldMetadatas.map(
(indexFieldMetadata) =>
removePropertiesFromRecord(indexFieldMetadata, [
(indexFieldMetadata) => ({
...removePropertiesFromRecord(indexFieldMetadata, [
'indexMetadata',
'fieldMetadata',
]),
createdAt: indexFieldMetadata.createdAt.toISOString(),
updatedAt: indexFieldMetadata.updatedAt.toISOString(),
}),
),
};
};
@@ -9,7 +9,7 @@ type FlatObjectMetadataOverrides = Required<
export const getFlatObjectMetadataMock = (
overrides: FlatObjectMetadataOverrides,
): FlatObjectMetadata => {
const createdAt = '2024-01-01T00:00:00.000Z' as unknown as Date;
const createdAt = '2024-01-01T00:00:00.000Z';
return {
viewIds: [],
@@ -54,7 +54,7 @@ export const fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCre
},
workspaceId,
});
const createdAt = new Date();
const createdAt = new Date().toISOString();
const flatObjectMetadataToCreate: FlatObjectMetadata = {
fieldMetadataIds: [],
viewIds: [],
@@ -16,6 +16,8 @@ export const fromObjectMetadataEntityToFlatObjectMetadata = (
return {
...objectMetadataEntityWithoutRelations,
createdAt: objectMetadataEntity.createdAt.toISOString(),
updatedAt: objectMetadataEntity.updatedAt.toISOString(),
viewIds: objectMetadataEntity.views.map((viewEntity) => viewEntity.id),
indexMetadataIds: objectMetadataEntity.indexMetadatas.map(
(indexEntity) => indexEntity.id,
@@ -1,4 +1,4 @@
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
import {
WORKSPACE_MIGRATION_OBJECT_ACTION_TYPES,
@@ -7,7 +7,7 @@ import {
import { type FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type';
export const isFailedFlatObjectMetadataValidation = (
failedValidation: FailedFlatEntityValidation<FlatEntity>,
failedValidation: FailedFlatEntityValidation<SyncableFlatEntity>,
): failedValidation is FailedFlatEntityValidation<FlatObjectMetadata> => {
return WORKSPACE_MIGRATION_OBJECT_ACTION_TYPES.includes(
failedValidation.type as WorkspaceMigrationObjectActionTypeV2,
@@ -52,7 +52,7 @@ export const recomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdate = ({
if (!isDefined(labelMetadataIdentifierViewField)) {
const viewFieldId = v4();
const createdAt = new Date();
const createdAt = new Date().toISOString();
const flatViewFieldToCreate: FlatViewField = {
fieldMetadataId: updatedLabelIdentifierFieldMetadataId,
position: lowestViewFieldPosition - 1,
@@ -5,9 +5,9 @@ export const transformPageLayoutTabEntityToFlatPageLayoutTab = (
pageLayoutTabEntity: PageLayoutTabEntity,
): FlatPageLayoutTab => {
return {
createdAt: pageLayoutTabEntity.createdAt,
deletedAt: pageLayoutTabEntity.deletedAt,
updatedAt: pageLayoutTabEntity.updatedAt,
createdAt: pageLayoutTabEntity.createdAt.toISOString(),
deletedAt: pageLayoutTabEntity.deletedAt?.toISOString() ?? null,
updatedAt: pageLayoutTabEntity.updatedAt.toISOString(),
id: pageLayoutTabEntity.id,
title: pageLayoutTabEntity.title,
position: pageLayoutTabEntity.position,
@@ -23,7 +23,7 @@ export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
['pageLayoutTabId'],
);
const createdAt = new Date();
const createdAt = new Date().toISOString();
const pageLayoutWidgetId = v4();
return {
@@ -36,6 +36,6 @@ export const fromDeletePageLayoutWidgetInputToFlatPageLayoutWidgetOrThrow = ({
return {
...existingFlatPageLayoutWidgetToDelete,
deletedAt: new Date(),
deletedAt: new Date().toISOString(),
};
};
@@ -14,6 +14,9 @@ export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = (
return {
...pageLayoutWidgetEntityWithoutRelations,
createdAt: pageLayoutWidgetEntity.createdAt.toISOString(),
updatedAt: pageLayoutWidgetEntity.updatedAt.toISOString(),
deletedAt: pageLayoutWidgetEntity.deletedAt?.toISOString() ?? null,
universalIdentifier:
pageLayoutWidgetEntityWithoutRelations.universalIdentifier ??
pageLayoutWidgetEntityWithoutRelations.id,
@@ -5,9 +5,9 @@ export const transformPageLayoutEntityToFlatPageLayout = (
pageLayoutEntity: PageLayoutEntity,
): FlatPageLayout => {
return {
createdAt: pageLayoutEntity.createdAt,
deletedAt: pageLayoutEntity.deletedAt,
updatedAt: pageLayoutEntity.updatedAt,
createdAt: pageLayoutEntity.createdAt.toISOString(),
deletedAt: pageLayoutEntity.deletedAt?.toISOString() ?? null,
updatedAt: pageLayoutEntity.updatedAt.toISOString(),
id: pageLayoutEntity.id,
name: pageLayoutEntity.name,
type: pageLayoutEntity.type,
@@ -14,7 +14,7 @@ export const fromRoleTargetsEntityToFlatRoleTarget = (
targetApplicationId: roleTarget.targetApplicationId,
applicationId: roleTarget.applicationId,
universalIdentifier: roleTarget.universalIdentifier ?? roleTarget.id,
createdAt: roleTarget.createdAt,
updatedAt: roleTarget.updatedAt,
createdAt: roleTarget.createdAt.toISOString(),
updatedAt: roleTarget.updatedAt.toISOString(),
};
};
@@ -13,7 +13,7 @@ export const fromCreateRoleInputToFlatRoleToCreate = ({
workspaceId: string;
applicationId: string;
}): FlatRole => {
const now = new Date();
const now = new Date().toISOString();
const {
label,
@@ -20,8 +20,8 @@ export const fromRoleEntityToFlatRole = (role: RoleEntity): FlatRole => {
canBeAssignedToApiKeys: role.canBeAssignedToApiKeys,
canBeAssignedToApplications: role.canBeAssignedToApplications,
workspaceId: role.workspaceId,
createdAt: role.createdAt,
updatedAt: role.updatedAt,
createdAt: role.createdAt.toISOString(),
updatedAt: role.updatedAt.toISOString(),
universalIdentifier: role.universalIdentifier ?? role.standardId ?? role.id,
applicationId: role.applicationId ?? null,
roleTargetIds: role.roleTargets.map((rt) => rt.id),
@@ -7,7 +7,7 @@ export const fromStandardRoleDefinitionToFlatRole = (
standardRoleDefinition: StandardRoleDefinition,
workspaceId: string,
): FlatRole => {
const createdAt = new Date();
const createdAt = new Date().toISOString();
return {
...standardRoleDefinition,
@@ -22,7 +22,7 @@ export const fromCreateViewFieldInputToFlatViewFieldToCreate = ({
['aggregateOperation', 'fieldMetadataId', 'id', 'viewId'],
);
const createdAt = new Date();
const createdAt = new Date().toISOString();
const viewFieldId = createViewFieldInput.id ?? v4();
return {
@@ -35,6 +35,6 @@ export const fromDeleteViewFieldInputToFlatViewFieldOrThrow = ({
return {
...existingFlatViewFieldToDelete,
deletedAt: new Date(),
deletedAt: new Date().toISOString(),
};
};
@@ -14,6 +14,9 @@ export const fromViewFieldEntityToFlatViewField = (
return {
...viewFieldEntityWithoutRelations,
createdAt: viewFieldEntity.createdAt.toISOString(),
updatedAt: viewFieldEntity.updatedAt.toISOString(),
deletedAt: viewFieldEntity.deletedAt?.toISOString() ?? null,
universalIdentifier:
viewFieldEntityWithoutRelations.universalIdentifier ??
viewFieldEntityWithoutRelations.id,
@@ -27,7 +27,7 @@ export const fromCreateViewFilterInputToFlatViewFilterToCreate = ({
],
);
const createdAt = new Date();
const createdAt = new Date().toISOString();
const viewFilterId = createViewFilterInput.id ?? v4();
return {
@@ -35,6 +35,6 @@ export const fromDeleteViewFilterInputToFlatViewFilterOrThrow = ({
return {
...existingFlatViewFilterToDelete,
deletedAt: new Date(),
deletedAt: new Date().toISOString(),
};
};
@@ -14,6 +14,9 @@ export const fromViewFilterEntityToFlatViewFilter = (
return {
...viewFilterEntityWithoutRelations,
createdAt: viewFilterEntity.createdAt.toISOString(),
updatedAt: viewFilterEntity.updatedAt.toISOString(),
deletedAt: viewFilterEntity.deletedAt?.toISOString() ?? null,
universalIdentifier:
viewFilterEntityWithoutRelations.universalIdentifier ??
viewFilterEntityWithoutRelations.id,
@@ -28,7 +28,7 @@ export const computeFlatViewGroupsOnViewCreate = ({
);
}
const createdAt = new Date();
const createdAt = new Date().toISOString();
const flatViewGroupsFromOptions: FlatViewGroup[] = (
mainGroupByFieldMetadata.options ?? []
@@ -21,7 +21,7 @@ export const fromCreateViewGroupInputToFlatViewGroupToCreate = ({
['fieldValue', 'id', 'viewId'],
);
const createdAt = new Date();
const createdAt = new Date().toISOString();
const viewGroupId = createViewGroupInput.id ?? v4();
return {
@@ -35,6 +35,6 @@ export const fromDeleteViewGroupInputToFlatViewGroupOrThrow = ({
return {
...existingFlatViewGroupToDelete,
deletedAt: new Date(),
deletedAt: new Date().toISOString(),
};
};
@@ -14,6 +14,9 @@ export const fromViewGroupEntityToFlatViewGroup = (
return {
...viewGroupEntityWithoutRelations,
createdAt: viewGroupEntity.createdAt.toISOString(),
updatedAt: viewGroupEntity.updatedAt.toISOString(),
deletedAt: viewGroupEntity.deletedAt?.toISOString() ?? null,
universalIdentifier:
viewGroupEntityWithoutRelations.universalIdentifier ??
viewGroupEntityWithoutRelations.id,
@@ -35,7 +35,7 @@ export const fromCreateViewInputToFlatViewToCreate = ({
['id', 'name', 'objectMetadataId'],
);
const createdAt = new Date();
const createdAt = new Date().toISOString();
const viewId = createViewInput.id ?? v4();
const flatViewToCreate = {
@@ -35,6 +35,6 @@ export const fromDeleteViewInputToFlatViewOrThrow = ({
return {
...existingFlatViewToDelete,
deletedAt: new Date(),
deletedAt: new Date().toISOString(),
};
};
@@ -12,6 +12,9 @@ export const fromViewEntityToFlatView = (viewEntity: ViewEntity): FlatView => {
return {
...viewEntityWithoutRelations,
createdAt: viewEntity.createdAt.toISOString(),
updatedAt: viewEntity.updatedAt.toISOString(),
deletedAt: viewEntity.deletedAt?.toISOString() ?? null,
universalIdentifier:
viewEntityWithoutRelations.universalIdentifier ??
viewEntityWithoutRelations.id,
@@ -23,16 +23,16 @@ export const buildDefaultIndexesForCustomObject = ({
const tsVectorFlatIndex = generateFlatIndexMetadataWithNameOrThrow({
objectFlatFieldMetadatas,
flatIndex: {
createdAt,
createdAt: createdAt.toISOString(),
flatIndexFieldMetadatas: [
{
createdAt,
createdAt: createdAt.toISOString(),
fieldMetadataId:
defaultFlatFieldForCustomObjectMaps.fields.searchVectorField.id,
id: v4(),
indexMetadataId: tsFlatVectorIndexId,
order: 0,
updatedAt: createdAt,
updatedAt: createdAt.toISOString(),
},
],
id: tsFlatVectorIndexId,
@@ -42,7 +42,7 @@ export const buildDefaultIndexesForCustomObject = ({
isUnique: false,
objectMetadataId: flatObjectMetadata.id,
universalIdentifier: tsFlatVectorIndexId,
updatedAt: createdAt,
updatedAt: createdAt.toISOString(),
workspaceId,
applicationId: flatObjectMetadata.applicationId ?? null,
},
@@ -1,5 +1,5 @@
import { v4 } from 'uuid';
import { isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { type FlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/types/flat-role-target.type';
@@ -28,8 +28,8 @@ export const fromCreateRoleTargetInputToFlatRoleTargetToCreate = ({
agentId: null,
apiKeyId: null,
targetApplicationId: null,
createdAt: now,
updatedAt: now,
createdAt: now.toISOString(),
updatedAt: now.toISOString(),
universalIdentifier: universalIdentifier ?? v4(),
workspaceId,
applicationId: createRoleTargetInput.applicationId,
@@ -288,6 +288,9 @@ export class RoleResolver {
return agents.map((agentEntity) =>
fromFlatAgentWithRoleIdToAgentDto({
...agentEntity,
createdAt: agentEntity.createdAt.toISOString(),
updatedAt: agentEntity.updatedAt.toISOString(),
deletedAt: agentEntity.deletedAt?.toISOString() ?? null,
universalIdentifier: agentEntity.universalIdentifier ?? agentEntity.id,
roleId: role.id,
}),
@@ -44,6 +44,8 @@ export class WorkspaceFlatRouteTriggerMapCacheService extends WorkspaceCacheProv
...removePropertiesFromRecord(routeTriggerEntity, [
...ROUTE_TRIGGER_ENTITY_RELATION_PROPERTIES,
]),
createdAt: routeTriggerEntity.createdAt.toISOString(),
updatedAt: routeTriggerEntity.updatedAt.toISOString(),
universalIdentifier:
routeTriggerEntity.universalIdentifier ?? routeTriggerEntity.id,
} satisfies FlatRouteTrigger;
@@ -23,8 +23,8 @@ export const fromCreateRouteTriggerInputToFlatRouteTrigger = ({
httpMethod: createRouteTriggerInput.httpMethod,
serverlessFunctionId: createRouteTriggerInput.serverlessFunctionId,
workspaceId,
createdAt: now,
updatedAt: now,
createdAt: now.toISOString(),
updatedAt: now.toISOString(),
applicationId: workspaceCustomApplicationId,
};
};
@@ -25,9 +25,9 @@ export const fromUpdateRouteTriggerInputToFlatRouteTriggerToUpdateOrThrow = ({
return {
...existingFlatRouteTrigger,
updatedAt: new Date().toISOString(),
path: updateRouteTriggerInput.update.path,
isAuthRequired: updateRouteTriggerInput.update.isAuthRequired,
httpMethod: updateRouteTriggerInput.update.httpMethod,
updatedAt: new Date(),
};
};
@@ -179,7 +179,7 @@ export class ServerlessFunctionV2Service {
const optimisticallyUpdatedFlatServerlessFunctionWithDeletedAt = {
...existingFlatServerlessFunction,
deletedAt: new Date(),
deletedAt: new Date().toISOString(),
};
const validateAndBuildResult =
@@ -38,8 +38,8 @@ export const fromCreateServerlessFunctionInputToFlatServerlessFunction = ({
rawCreateServerlessFunctionInput.handlerName ?? DEFAULT_HANDLER_NAME,
universalIdentifier:
rawCreateServerlessFunctionInput.universalIdentifier ?? id,
createdAt: currentDate,
updatedAt: currentDate,
createdAt: currentDate.toISOString(),
updatedAt: currentDate.toISOString(),
deletedAt: null,
latestVersion: null,
publishedVersions: [],
@@ -19,6 +19,9 @@ export const fromServerlessFunctionEntityToFlatServerlessFunction = (
return {
...serverlessFunctionWithoutRelations,
createdAt: serverlessFunctionEntity.createdAt.toISOString(),
updatedAt: serverlessFunctionEntity.updatedAt.toISOString(),
deletedAt: serverlessFunctionEntity.deletedAt?.toISOString() ?? null,
cronTriggerIds:
serverlessFunctionEntity.cronTriggers.map((el) => el.id) ?? [],
routeTriggerIds:
@@ -22,6 +22,7 @@ import {
ViewFieldException,
ViewFieldExceptionCode,
} from 'src/engine/metadata-modules/view-field/exceptions/view-field.exception';
import { fromFlatViewFieldToViewFieldDto } from 'src/engine/metadata-modules/view-field/utils/from-flat-view-field-to-view-field-dto.util';
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
@@ -117,7 +118,7 @@ export class ViewFieldV2Service {
return findManyFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityIds: flatViewFieldsToCreate.map((el) => el.id),
flatEntityMaps: recomputedExistingFlatViewFieldMaps,
});
}).map(fromFlatViewFieldToViewFieldDto);
}
async updateOne({
@@ -171,10 +172,12 @@ export class ViewFieldV2Service {
},
);
return findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatView.id,
flatEntityMaps: recomputedExistingFlatViewFieldMaps,
});
return fromFlatViewFieldToViewFieldDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatView.id,
flatEntityMaps: recomputedExistingFlatViewFieldMaps,
}),
);
}
async deleteOne({
@@ -228,10 +231,12 @@ export class ViewFieldV2Service {
},
);
return findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatViewWithDeletedAt.id,
flatEntityMaps: recomputedExistingFlatViewFieldMaps,
});
return fromFlatViewFieldToViewFieldDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatViewWithDeletedAt.id,
flatEntityMaps: recomputedExistingFlatViewFieldMaps,
}),
);
}
async destroyOne({
@@ -277,7 +282,7 @@ export class ViewFieldV2Service {
);
}
return existingViewFieldToDelete;
return fromFlatViewFieldToViewFieldDto(existingViewFieldToDelete);
}
async findByWorkspaceId(workspaceId: string): Promise<ViewFieldEntity[]> {
@@ -0,0 +1,15 @@
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
import { type ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto';
export const fromFlatViewFieldToViewFieldDto = (
flatViewField: FlatViewField,
): ViewFieldDTO => {
const { createdAt, updatedAt, deletedAt, ...rest } = flatViewField;
return {
...rest,
createdAt: new Date(createdAt),
updatedAt: new Date(updatedAt),
deletedAt: deletedAt ? new Date(deletedAt) : null,
};
};
@@ -17,6 +17,7 @@ import { DestroyViewFilterInput } from 'src/engine/metadata-modules/view-filter/
import { UpdateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input';
import { ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto';
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
import { fromFlatViewFilterToViewFilterDto } from 'src/engine/metadata-modules/view-filter/utils/from-flat-view-filter-to-view-filter-dto.util';
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
@@ -86,10 +87,12 @@ export class ViewFilterService {
},
);
return findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatViewFilterToCreate.id,
flatEntityMaps: recomputedExistingFlatViewFilterMaps,
});
return fromFlatViewFilterToViewFilterDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatViewFilterToCreate.id,
flatEntityMaps: recomputedExistingFlatViewFilterMaps,
}),
);
}
async updateOne({
@@ -143,10 +146,12 @@ export class ViewFilterService {
},
);
return findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatViewFilter.id,
flatEntityMaps: recomputedExistingFlatViewFilterMaps,
});
return fromFlatViewFilterToViewFilterDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatViewFilter.id,
flatEntityMaps: recomputedExistingFlatViewFilterMaps,
}),
);
}
async deleteOne({
@@ -202,10 +207,12 @@ export class ViewFilterService {
},
);
return findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatViewFilterWithDeletedAt.id,
flatEntityMaps: recomputedExistingFlatViewFilterMaps,
});
return fromFlatViewFilterToViewFilterDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatViewFilterWithDeletedAt.id,
flatEntityMaps: recomputedExistingFlatViewFilterMaps,
}),
);
}
async destroyOne({
@@ -251,7 +258,7 @@ export class ViewFilterService {
);
}
return existingViewFilterToDelete;
return fromFlatViewFilterToViewFilterDto(existingViewFilterToDelete);
}
async findByWorkspaceId(workspaceId: string): Promise<ViewFilterEntity[]> {
@@ -0,0 +1,15 @@
import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type';
import { type ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto';
export const fromFlatViewFilterToViewFilterDto = (
flatViewFilter: FlatViewFilter,
): ViewFilterDTO => {
const { createdAt, updatedAt, deletedAt, ...rest } = flatViewFilter;
return {
...rest,
createdAt: new Date(createdAt),
updatedAt: new Date(updatedAt),
deletedAt: deletedAt ? new Date(deletedAt) : null,
};
};
@@ -22,6 +22,7 @@ import {
ViewGroupException,
ViewGroupExceptionCode,
} from 'src/engine/metadata-modules/view-group/exceptions/view-group.exception';
import { fromFlatViewGroupToViewGroupDto } from 'src/engine/metadata-modules/view-group/utils/from-flat-view-group-to-view-group-dto.util';
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
@@ -138,7 +139,7 @@ export class ViewGroupService {
return findManyFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityIds: flatViewGroupsToCreate.map((el) => el.id),
flatEntityMaps: recomputedExistingFlatViewGroupMaps,
});
}).map(fromFlatViewGroupToViewGroupDto);
}
async updateOne({
@@ -192,10 +193,12 @@ export class ViewGroupService {
},
);
return findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatViewGroup.id,
flatEntityMaps: recomputedExistingFlatViewGroupMaps,
});
return fromFlatViewGroupToViewGroupDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatViewGroup.id,
flatEntityMaps: recomputedExistingFlatViewGroupMaps,
}),
);
}
async deleteOne({
@@ -251,10 +254,12 @@ export class ViewGroupService {
},
);
return findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatViewGroupWithDeletedAt.id,
flatEntityMaps: recomputedExistingFlatViewGroupMaps,
});
return fromFlatViewGroupToViewGroupDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: optimisticallyUpdatedFlatViewGroupWithDeletedAt.id,
flatEntityMaps: recomputedExistingFlatViewGroupMaps,
}),
);
}
async destroyOne({
@@ -300,7 +305,7 @@ export class ViewGroupService {
);
}
return existingViewGroupToDelete;
return fromFlatViewGroupToViewGroupDto(existingViewGroupToDelete);
}
async findByWorkspaceId(workspaceId: string): Promise<ViewGroupEntity[]> {
@@ -0,0 +1,15 @@
import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type';
import { type ViewGroupDTO } from 'src/engine/metadata-modules/view-group/dtos/view-group.dto';
export const fromFlatViewGroupToViewGroupDto = (
flatViewGroup: FlatViewGroup,
): ViewGroupDTO => {
const { createdAt, updatedAt, deletedAt, ...rest } = flatViewGroup;
return {
...rest,
createdAt: new Date(createdAt),
updatedAt: new Date(updatedAt),
deletedAt: deletedAt ? new Date(deletedAt) : null,
};
};
@@ -21,6 +21,7 @@ import { UpdateViewInput } from 'src/engine/metadata-modules/view/dtos/inputs/up
import { ViewDTO } from 'src/engine/metadata-modules/view/dtos/view.dto';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { ViewVisibility } from 'src/engine/metadata-modules/view/enums/view-visibility.enum';
import { fromFlatViewToViewDto } from 'src/engine/metadata-modules/view/utils/from-flat-view-to-view-dto.util';
import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
@@ -104,10 +105,12 @@ export class ViewService {
},
);
return findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatViewToCreate.id,
flatEntityMaps: recomputedExistingFlatViewMaps,
});
return fromFlatViewToViewDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatViewToCreate.id,
flatEntityMaps: recomputedExistingFlatViewMaps,
}),
);
}
async updateOne({
@@ -178,10 +181,12 @@ export class ViewService {
},
);
return findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: updateViewInput.id,
flatEntityMaps: recomputedExistingFlatViewMaps,
});
return fromFlatViewToViewDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: updateViewInput.id,
flatEntityMaps: recomputedExistingFlatViewMaps,
}),
);
}
async deleteOne({
@@ -235,10 +240,12 @@ export class ViewService {
},
);
return findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: deleteViewInput.id,
flatEntityMaps: recomputedExistingFlatViewMaps,
});
return fromFlatViewToViewDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: deleteViewInput.id,
flatEntityMaps: recomputedExistingFlatViewMaps,
}),
);
}
async destroyOne({
@@ -283,7 +290,7 @@ export class ViewService {
);
}
return flatViewFromDestroyInput;
return fromFlatViewToViewDto(flatViewFromDestroyInput);
}
processViewNameWithTemplate(
@@ -0,0 +1,13 @@
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
import { type ViewDTO } from 'src/engine/metadata-modules/view/dtos/view.dto';
export const fromFlatViewToViewDto = (flatView: FlatView): ViewDTO => {
const { createdAt, updatedAt, deletedAt, ...rest } = flatView;
return {
...rest,
createdAt: new Date(createdAt),
updatedAt: new Date(updatedAt),
deletedAt: deletedAt ? new Date(deletedAt) : null,
};
};
@@ -114,8 +114,8 @@ describe('WorkspaceEntityManager', () => {
isLabelSyncedWithName: false,
isUIReadOnly: false,
duplicateCriteria: null,
createdAt: new Date(),
updatedAt: new Date(),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
(getObjectMetadataFromEntityTarget as jest.Mock).mockReturnValue(
@@ -30,8 +30,8 @@ describe('getColumnNameToFieldMetadataIdMap', () => {
viewIds: [],
applicationId: null,
isLabelSyncedWithName: false,
createdAt: new Date(),
updatedAt: new Date(),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
shortcut: null,
description: null,
standardOverrides: null,
@@ -30,8 +30,8 @@ describe('getFieldMetadataIdToColumnNamesMap', () => {
viewIds: [],
applicationId: null,
isLabelSyncedWithName: false,
createdAt: new Date(),
updatedAt: new Date(),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
shortcut: null,
description: null,
standardOverrides: null,
@@ -78,7 +78,7 @@ export const createStandardIndexFlatMetadata = <
return generateFlatIndexMetadataWithNameOrThrow({
flatIndex: {
createdAt: now,
createdAt: now.toISOString(),
applicationId: twentyStandardApplicationId,
indexType,
indexWhereClause,
@@ -86,17 +86,17 @@ export const createStandardIndexFlatMetadata = <
isUnique,
objectMetadataId,
universalIdentifier: indexDefinition.universalIdentifier,
updatedAt: now,
updatedAt: now.toISOString(),
workspaceId,
id: indexId,
flatIndexFieldMetadatas: flatFieldMetadatas.map<FlatIndexFieldMetadata>(
({ id: fieldMetadataId }, index) => ({
createdAt: now,
createdAt: now.toISOString(),
fieldMetadataId,
id: v4(),
indexMetadataId: indexId,
order: index,
updatedAt: now,
updatedAt: now.toISOString(),
}),
),
},
@@ -81,7 +81,7 @@ export const createStandardObjectFlatMetadata = <
fieldMetadataIds: [],
indexMetadataIds: [],
viewIds: [],
createdAt: now,
updatedAt: now,
createdAt: now.toISOString(),
updatedAt: now.toISOString(),
id: standardFieldMetadataIdByObjectAndFieldName[nameSingular].id,
});
@@ -0,0 +1,5 @@
export type ExtractRecordTypeOrmNonNullableDateProperties<T> = NonNullable<
{
[P in keyof T]: null extends T[P] ? never : T[P] extends Date ? P : never;
}[keyof T]
>;
@@ -0,0 +1,9 @@
export type ExtractRecordTypeOrmNullableDateProperties<T> = NonNullable<
{
[P in keyof T]: null extends T[P]
? NonNullable<T[P]> extends Date
? P
: never
: never;
}[keyof T]
>;
@@ -5,17 +5,17 @@ import {
FlatEntityMapsExceptionCode,
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
type AddFlatEntityToFlatEntityMapsThroughMutationOrThrowArgs<
T extends FlatEntity,
T extends SyncableFlatEntity,
> = {
flatEntity: T;
flatEntityMapsToMutate: FlatEntityMaps<T>;
};
export const addFlatEntityToFlatEntityMapsThroughMutationOrThrow = <
T extends FlatEntity,
T extends SyncableFlatEntity,
>({
flatEntity,
flatEntityMapsToMutate,
@@ -5,17 +5,17 @@ import {
FlatEntityMapsExceptionCode,
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
export type DeleteFlatEntityFromFlatEntityMapsThroughMutationOrThrowArgs<
T extends FlatEntity,
T extends SyncableFlatEntity,
> = {
entityToDeleteId: string;
flatEntityMapsToMutate: FlatEntityMaps<T>;
};
export const deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow = <
T extends FlatEntity,
T extends SyncableFlatEntity,
>({
flatEntityMapsToMutate,
entityToDeleteId,
@@ -1,17 +1,17 @@
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
import { deleteFlatEntityFromFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/delete-flat-entity-from-flat-entity-maps-through-mutation-or-throw.util';
export type ReplaceFlatEntityInFlatEntityMapsThroughMutationOrThrowArgs<
T extends FlatEntity,
T extends SyncableFlatEntity,
> = {
flatEntity: T;
flatEntityMapsToMutate: FlatEntityMaps<T>;
};
export const replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow = <
T extends FlatEntity,
T extends SyncableFlatEntity,
>({
flatEntity,
flatEntityMapsToMutate,
@@ -1,6 +1,6 @@
import { type MessageDescriptor } from '@lingui/core';
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type WorkspaceMigrationActionTypeV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2';
export type FlatEntityValidationError<TCode extends string = string> = {
@@ -10,7 +10,7 @@ export type FlatEntityValidationError<TCode extends string = string> = {
value?: unknown;
};
export type FailedFlatEntityValidation<T extends FlatEntity> = {
export type FailedFlatEntityValidation<T extends SyncableFlatEntity> = {
type: WorkspaceMigrationActionTypeV2;
errors: FlatEntityValidationError[];
flatEntityMinimalInformation: Partial<T>;
@@ -35,7 +35,7 @@ export class WorkspaceAgentComparator {
}: WorkspaceAgentComparatorArgs): AgentComparatorResult[] {
const results: AgentComparatorResult[] = [];
const keyFactory = (agent: FlatAgent) => agent.universalIdentifier;
const keyFactory = (agent: FlatAgent) => agent.universalIdentifier ?? '';
const fromAgentMap = transformMetadataForComparison(fromFlatAgents, {
shouldIgnoreProperty: (property) =>
@@ -31,7 +31,7 @@ export class StandardRoleFactory {
...flatRole,
id: existingRole.id,
universalIdentifier: roleDefinition.standardId || existingRole.id,
createdAt: existingRole.createdAt,
createdAt: existingRole.createdAt.toISOString(),
});
} else {
computedRoles.push({
@@ -7,7 +7,8 @@ import type { ApplicationEntity } from 'src/engine/core-modules/application/appl
})
export abstract class SyncableEntity {
@Column({ nullable: true, type: 'uuid' })
universalIdentifier: string | null;
// TODO should not be nullable
universalIdentifier: string;
@Column({ nullable: true, type: 'uuid' })
applicationId: string | null;
@@ -36,8 +36,8 @@ describe('WorkflowDatabaseEventTriggerListener', () => {
isRemote: false,
isAuditLogged: true,
isSearchable: true,
createdAt: new Date(),
updatedAt: new Date(),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
icon: 'Icon123',
universalIdentifier: 'test-object-metadata',
fieldMetadataIds: [],