From a07590eba52536102123422ad087af64ba86d971 Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Fri, 23 Jan 2026 19:22:01 +0100 Subject: [PATCH] Change `formatResult` to return string instead of `Date` object for `DATE_TIME` (#17407) This PR modifies our broadly used `formatResult` util to counter act TypeORM transforming any date time to a `Date` object. Instead we return the ISO string for any `DATE_TIME`, this way we're not transporting Date object from one function to another in the backend. We do this because there was problems working with events utils that take string date time in parameters and received Date objects. As this is a recurring problem and because it's an opinionated choice from TypeORM, we chose to switch to string only in our codebase, from TypeORM's output to frontend. --- .../twenty-orm/utils/format-result.util.ts | 33 +++++++++++++++++++ ...-input-validation.integration-spec.ts.snap | 4 +-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/format-result.util.ts b/packages/twenty-server/src/engine/twenty-orm/utils/format-result.util.ts index 673c2d6d0a..ed8949c2c5 100644 --- a/packages/twenty-server/src/engine/twenty-orm/utils/format-result.util.ts +++ b/packages/twenty-server/src/engine/twenty-orm/utils/format-result.util.ts @@ -182,6 +182,39 @@ export function formatResult( newData[dateField.name] = rawUpdatedDate; } + const fieldMetadataItemsOfTypeDateTimeOnly = + getFlatFieldsFromFlatObjectMetadata( + flatObjectMetadata, + flatFieldMetadataMaps, + ).filter((field) => field.type === FieldMetadataType.DATE_TIME); + + for (const dateTimeField of fieldMetadataItemsOfTypeDateTimeOnly) { + // @ts-expect-error legacy noImplicitAny + const rawUpdatedDateTime = newData[dateTimeField.name] as + | string + | Date + | null + | undefined; + + if (!isDefined(rawUpdatedDateTime)) { + continue; + } + + if (typeof rawUpdatedDateTime === 'string') { + // @ts-expect-error legacy noImplicitAny + newData[dateTimeField.name] = rawUpdatedDateTime; + } else if (rawUpdatedDateTime instanceof Date) { + const dateIsoString = rawUpdatedDateTime.toISOString(); + + // @ts-expect-error legacy noImplicitAny + newData[dateTimeField.name] = dateIsoString; + } else { + throw new Error( + `Invalid DATE_TIME field "${dateTimeField.name}", value: "${rawUpdatedDateTime}", it should be a string or Date instance, (current type : ${typeof rawUpdatedDateTime}).`, + ); + } + } + return newData as T; } diff --git a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/__snapshots__/date-time-field-create-input-validation.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/__snapshots__/date-time-field-create-input-validation.integration-spec.ts.snap index 2625772ebd..230e817f8e 100644 --- a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/__snapshots__/date-time-field-create-input-validation.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/__snapshots__/date-time-field-create-input-validation.integration-spec.ts.snap @@ -6,7 +6,7 @@ exports[`Create input validation - DATE_TIME Gql create input - failure DATE_TIM exports[`Create input validation - DATE_TIME Gql create input - failure DATE_TIME - should fail with : {"dateTimeField":{}} 1`] = `"Invalid value {} for date or date-time field "dateTimeField""`; -exports[`Create input validation - DATE_TIME Gql create input - failure DATE_TIME - should fail with : {"dateTimeField":1} 1`] = `"invalid input syntax for type timestamp with time zone: "1""`; +exports[`Create input validation - DATE_TIME Gql create input - failure DATE_TIME - should fail with : {"dateTimeField":1} 1`] = `"Invalid DATE_TIME field "dateTimeField", value: "1", it should be a string or Date instance, (current type : number)."`; exports[`Create input validation - DATE_TIME Gql create input - failure DATE_TIME - should fail with : {"dateTimeField":true} 1`] = `"Invalid value true for date or date-time field "dateTimeField""`; @@ -16,6 +16,6 @@ exports[`Create input validation - DATE_TIME Rest create input - failure DATE_TI exports[`Create input validation - DATE_TIME Rest create input - failure DATE_TIME - should fail with : {"dateTimeField":{}} 1`] = `"["Invalid value {} for date or date-time field \\"dateTimeField\\""]"`; -exports[`Create input validation - DATE_TIME Rest create input - failure DATE_TIME - should fail with : {"dateTimeField":1} 1`] = `"["invalid input syntax for type timestamp with time zone: \\"1\\""]"`; +exports[`Create input validation - DATE_TIME Rest create input - failure DATE_TIME - should fail with : {"dateTimeField":1} 1`] = `"["Invalid DATE_TIME field \\"dateTimeField\\", value: \\"1\\", it should be a string or Date instance, (current type : number)."]"`; exports[`Create input validation - DATE_TIME Rest create input - failure DATE_TIME - should fail with : {"dateTimeField":true} 1`] = `"["Invalid value true for date or date-time field \\"dateTimeField\\""]"`;