common api - null equivalence (#15926)
closes https://github.com/twentyhq/core-team-issues/issues/1629 To do before requesting review : - filter update Migration to come in an other PR Strat : 1/ Null transformation - [x] Transform NULL equivalent value to NULL in field validation in common api - pre-query - with feature flag - [ ] Same logic in ORM (Not done, complex to handle feature flag here) - [x] Transform NULL value to equivalent in data formatting in ORM - post-query 2/ Migration (in other PR) for fieldMetadata not nullable with default defaultValue (empty string, ...) - [ ] Remove NOT NULL db constraint - [ ] Update record value to NULL - [ ] Update field metadata : isNullable:true - [ ] Update uniqueIndex whereClause (also for standard uniqueIndex) - [ ] Activate feature flag 3/ Update metadata creation - [x] No more default default value - [x] Update standard field nullability - [x] Remove index default whereClause for standard field 4/ Update filter - [x] When filtering on NULL or empty string, be sure all records are returned (the one with NULL + the one with "") 5/ Test - [ ] Strat. to do
This commit is contained in:
+1
@@ -16,4 +16,5 @@ export enum FeatureFlagKey {
|
||||
IS_WORKFLOW_RUN_STOPPAGE_ENABLED = 'IS_WORKFLOW_RUN_STOPPAGE_ENABLED',
|
||||
IS_DASHBOARD_V2_ENABLED = 'IS_DASHBOARD_V2_ENABLED',
|
||||
IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED = 'IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED',
|
||||
IS_NULL_EQUIVALENCE_ENABLED = 'IS_NULL_EQUIVALENCE_ENABLED',
|
||||
}
|
||||
|
||||
+2
@@ -128,11 +128,13 @@ export class UpsertRecordService {
|
||||
? conflictPathsUniqueFieldsToUpdate
|
||||
: ['id'];
|
||||
|
||||
//TODO : To delete once IS_NULL_EQUIVALENCE_ENABLED feature flag removed
|
||||
const indexPredicate = uniqueFieldsToUpdate
|
||||
.map((field) =>
|
||||
computeUniqueIndexWhereClause({
|
||||
type: field.type,
|
||||
name: field.name,
|
||||
defaultValue: field.defaultValue,
|
||||
}),
|
||||
)
|
||||
.filter(isDefined);
|
||||
|
||||
+17
-4
@@ -1,15 +1,21 @@
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const transformEmailsValue = (value: any): any => {
|
||||
export const transformEmailsValue = (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
value: any,
|
||||
isNullEquivalenceEnabled: boolean = false,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
): any => {
|
||||
if (!value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
let additionalEmails = value?.additionalEmails;
|
||||
let additionalEmails: string | null = value?.additionalEmails;
|
||||
const primaryEmail = value?.primaryEmail
|
||||
? value.primaryEmail.toLowerCase()
|
||||
: '';
|
||||
: isNullEquivalenceEnabled
|
||||
? null
|
||||
: '';
|
||||
|
||||
if (additionalEmails) {
|
||||
try {
|
||||
@@ -22,6 +28,13 @@ export const transformEmailsValue = (value: any): any => {
|
||||
additionalEmails = JSON.stringify(
|
||||
emailArray.map((email) => email.toLowerCase()),
|
||||
);
|
||||
|
||||
if (isNullEquivalenceEnabled) {
|
||||
additionalEmails =
|
||||
Array.isArray(emailArray) && emailArray.length === 0
|
||||
? null
|
||||
: additionalEmails;
|
||||
}
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,11 +1,11 @@
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import isEmpty from 'lodash.isempty';
|
||||
import { type LinkMetadataNullable } from 'twenty-shared/types';
|
||||
import {
|
||||
isDefined,
|
||||
lowercaseUrlOriginAndRemoveTrailingSlash,
|
||||
parseJson,
|
||||
} from 'twenty-shared/utils';
|
||||
import { type LinkMetadataNullable } from 'twenty-shared/types';
|
||||
|
||||
import { removeEmptyLinks } from 'src/engine/core-modules/record-transformer/utils/remove-empty-links';
|
||||
|
||||
|
||||
+4
-4
@@ -5,6 +5,10 @@ import {
|
||||
parsePhoneNumberWithError,
|
||||
} from 'libphonenumber-js';
|
||||
import isEmpty from 'lodash.isempty';
|
||||
import {
|
||||
type AdditionalPhoneMetadata,
|
||||
type PhonesMetadata,
|
||||
} from 'twenty-shared/types';
|
||||
import {
|
||||
getCountryCodesForCallingCode,
|
||||
isDefined,
|
||||
@@ -12,10 +16,6 @@ import {
|
||||
parseJson,
|
||||
removeUndefinedFields,
|
||||
} from 'twenty-shared/utils';
|
||||
import {
|
||||
type AdditionalPhoneMetadata,
|
||||
type PhonesMetadata,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import {
|
||||
RecordTransformerException,
|
||||
|
||||
Reference in New Issue
Block a user