fix: QueryRunner overrideDataByFieldMetadata sub fields not being stringified (#14187)

Adding `secondaryLinks` to company is broken, this fixes it

Regression can be traced back to this commit
https://github.com/twentyhq/twenty/pull/10912/files#diff-8a992c6bff80abc8c9075d585d293f6aa98c246df097efb4f904b82dc3ff8114R210-R214



https://github.com/user-attachments/assets/463cee62-8ee3-45dc-9912-fd8fb5244579
This commit is contained in:
neo773
2025-09-02 13:35:42 +05:30
committed by GitHub
parent d94e984a80
commit a7a79090cb
5 changed files with 50 additions and 33 deletions
@@ -52,7 +52,7 @@ export class RecordInputTransformerService {
return transformedEntries;
}
async transformFieldValue(
private async transformFieldValue(
fieldType: FieldMetadataType,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any,
@@ -7,7 +7,7 @@ describe('transformLinksValue', () => {
expect(transformLinksValue({})).toEqual({
primaryLinkLabel: null,
primaryLinkUrl: null,
secondaryLinks: '[]',
secondaryLinks: null,
});
});
@@ -16,13 +16,13 @@ describe('transformLinksValue', () => {
const input = {
primaryLinkUrl: 'HTTPS://EXAMPLE.COM',
primaryLinkLabel: 'Example',
secondaryLinks: '[]',
secondaryLinks: null,
};
const expected = {
primaryLinkUrl: 'https://example.com',
primaryLinkLabel: 'Example',
secondaryLinks: '[]',
secondaryLinks: null,
};
expect(transformLinksValue(input)).toEqual(expected);
@@ -32,13 +32,13 @@ describe('transformLinksValue', () => {
const input = {
primaryLinkUrl: 'https://example.com/',
primaryLinkLabel: 'Example',
secondaryLinks: '[]',
secondaryLinks: null,
};
const expected = {
primaryLinkUrl: 'https://example.com',
primaryLinkLabel: 'Example',
secondaryLinks: '[]',
secondaryLinks: null,
};
expect(transformLinksValue(input)).toEqual(expected);
@@ -48,13 +48,13 @@ describe('transformLinksValue', () => {
const input = {
primaryLinkUrl: 'example.com',
primaryLinkLabel: 'Example',
secondaryLinks: '[]',
secondaryLinks: null,
};
const expected = {
primaryLinkUrl: 'example.com',
primaryLinkLabel: 'Example',
secondaryLinks: '[]',
secondaryLinks: null,
};
expect(transformLinksValue(input)).toEqual(expected);
@@ -64,13 +64,13 @@ describe('transformLinksValue', () => {
const input = {
primaryLinkUrl: 'www.example.com',
primaryLinkLabel: 'Example',
secondaryLinks: '[]',
secondaryLinks: null,
};
const expected = {
primaryLinkUrl: 'www.example.com',
primaryLinkLabel: 'Example',
secondaryLinks: '[]',
secondaryLinks: null,
};
expect(transformLinksValue(input)).toEqual(expected);
@@ -1,4 +1,5 @@
import { isNonEmptyString } from '@sniptt/guards';
import isEmpty from 'lodash.isempty';
import {
isDefined,
lowercaseUrlOriginAndRemoveTrailingSlash,
@@ -41,19 +42,21 @@ export const transformLinksValue = (
},
);
const processedSecondaryLinks = secondaryLinks?.map((link) => ({
...link,
url: isDefined(link.url)
? lowercaseUrlOriginAndRemoveTrailingSlash(link.url)
: link.url,
}));
return {
...value,
primaryLinkUrl: isDefined(primaryLinkUrl)
? lowercaseUrlOriginAndRemoveTrailingSlash(primaryLinkUrl)
: primaryLinkUrl,
primaryLinkLabel,
secondaryLinks: JSON.stringify(
secondaryLinks?.map((link) => ({
...link,
url: isDefined(link.url)
? lowercaseUrlOriginAndRemoveTrailingSlash(link.url)
: link.url,
})),
),
secondaryLinks: isEmpty(processedSecondaryLinks)
? null
: JSON.stringify(processedSecondaryLinks),
};
};
@@ -4,10 +4,12 @@ import {
type CountryCallingCode,
parsePhoneNumberWithError,
} from 'libphonenumber-js';
import isEmpty from 'lodash.isempty';
import {
getCountryCodesForCallingCode,
isDefined,
isValidCountryCode,
parseJson,
removeUndefinedFields,
} from 'twenty-shared/utils';
@@ -23,7 +25,7 @@ import {
export type PhonesFieldGraphQLInput =
| Partial<
Omit<PhonesMetadata, 'additionalPhones'> & {
additionalPhones: Partial<AdditionalPhoneMetadata>[];
additionalPhones: string | null;
}
>
| null
@@ -194,12 +196,20 @@ export const transformPhonesValue = ({
number: primary.primaryPhoneNumber,
});
const parsedAdditionalPhones = isArray(additionalPhones)
? additionalPhones
: [];
const parsedAdditionalPhones = isNonEmptyString(additionalPhones)
? (parseJson<Partial<AdditionalPhoneMetadata>[]>(additionalPhones) ?? [])
: isArray(additionalPhones)
? additionalPhones
: [];
const validatedAdditionalPhones = parsedAdditionalPhones.map(
validateAndInferPhoneInput,
);
return removeUndefinedFields({
additionalPhones: parsedAdditionalPhones.map(validateAndInferPhoneInput),
additionalPhones: isEmpty(validatedAdditionalPhones)
? null
: JSON.stringify(validatedAdditionalPhones),
primaryPhoneCallingCode,
primaryPhoneCountryCode,
primaryPhoneNumber,