Null equivalence - remove feature flag (#16222)

This commit is contained in:
Etienne
2025-12-01 19:06:24 +01:00
committed by GitHub
parent da7536124e
commit 68c429a54a
23 changed files with 61 additions and 249 deletions
@@ -1287,7 +1287,6 @@ export enum FeatureFlagKey {
IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED = 'IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED',
IS_IMAP_SMTP_CALDAV_ENABLED = 'IS_IMAP_SMTP_CALDAV_ENABLED',
IS_JSON_FILTER_ENABLED = 'IS_JSON_FILTER_ENABLED',
IS_NULL_EQUIVALENCE_ENABLED = 'IS_NULL_EQUIVALENCE_ENABLED',
IS_PAGE_LAYOUT_ENABLED = 'IS_PAGE_LAYOUT_ENABLED',
IS_POSTGRESQL_INTEGRATION_ENABLED = 'IS_POSTGRESQL_INTEGRATION_ENABLED',
IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED',
@@ -1270,7 +1270,6 @@ export enum FeatureFlagKey {
IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED = 'IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED',
IS_IMAP_SMTP_CALDAV_ENABLED = 'IS_IMAP_SMTP_CALDAV_ENABLED',
IS_JSON_FILTER_ENABLED = 'IS_JSON_FILTER_ENABLED',
IS_NULL_EQUIVALENCE_ENABLED = 'IS_NULL_EQUIVALENCE_ENABLED',
IS_PAGE_LAYOUT_ENABLED = 'IS_PAGE_LAYOUT_ENABLED',
IS_POSTGRESQL_INTEGRATION_ENABLED = 'IS_POSTGRESQL_INTEGRATION_ENABLED',
IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED',
@@ -13,7 +13,6 @@ import { Repository } from 'typeorm';
import { ActiveOrSuspendedWorkspacesMigrationCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
import { RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
@@ -83,22 +82,6 @@ export class CleanNullEquivalentValuesCommand extends ActiveOrSuspendedWorkspace
this.logger.log('Dry run mode: No changes will be applied');
}
const featureFlag = await this.featureFlagRepository.findOne({
where: {
key: FeatureFlagKey.IS_NULL_EQUIVALENCE_ENABLED,
value: true,
workspaceId,
},
});
if (isDefined(featureFlag)) {
this.logger.log(
`Feature flag ${FeatureFlagKey.IS_NULL_EQUIVALENCE_ENABLED} already enabled for workspace ${workspaceId}`,
);
return;
}
const objectMetadataItems = await this.objectMetadataRepository.find({
where: { workspaceId },
relations: [
@@ -278,20 +261,6 @@ export class CleanNullEquivalentValuesCommand extends ActiveOrSuspendedWorkspace
}
}
}
if (!isDryRun) {
await this.featureFlagRepository.upsert(
{
key: FeatureFlagKey.IS_NULL_EQUIVALENCE_ENABLED,
value: true,
workspaceId,
},
['key', 'workspaceId'],
);
this.logger.log(
`Switched on feature flag ${FeatureFlagKey.IS_NULL_EQUIVALENCE_ENABLED} for workspace ${workspaceId}`,
);
}
}
private objectEquals(obj1: unknown, obj2: unknown): boolean {
@@ -44,7 +44,6 @@ import {
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service';
import { transformEmailsValue } from 'src/engine/core-modules/record-transformer/utils/transform-emails-value.util';
@@ -85,12 +84,6 @@ export class DataArgProcessor {
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
const isNullEquivalenceEnabled =
await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IS_NULL_EQUIVALENCE_ENABLED,
workspace.id,
);
const { fieldIdByName, fieldIdByJoinColumnName } =
buildFieldMapsFromFlatObjectMetadata(
flatFieldMetadataMaps,
@@ -141,7 +134,6 @@ export class DataArgProcessor {
fieldMetadata,
key,
value,
isNullEquivalenceEnabled,
);
}
processedRecords.push(processedRecord);
@@ -166,7 +158,6 @@ export class DataArgProcessor {
fieldMetadata: FlatFieldMetadata,
key: string,
value: unknown,
isNullEquivalenceEnabled: boolean,
): Promise<unknown> {
switch (fieldMetadata.type) {
case FieldMetadataType.POSITION:
@@ -182,7 +173,7 @@ export class DataArgProcessor {
case FieldMetadataType.TEXT: {
const validatedValue = validateTextFieldOrThrow(value, key);
return transformTextField(validatedValue, isNullEquivalenceEnabled);
return transformTextField(validatedValue);
}
case FieldMetadataType.DATE_TIME:
case FieldMetadataType.DATE:
@@ -207,19 +198,19 @@ export class DataArgProcessor {
fieldMetadata.options?.map((option) => option.value),
);
return transformArrayField(validatedValue, isNullEquivalenceEnabled);
return transformArrayField(validatedValue);
}
case FieldMetadataType.UUID:
return validateUUIDFieldOrThrow(value, key);
case FieldMetadataType.ARRAY: {
const validatedValue = validateArrayFieldOrThrow(value, key);
return transformArrayField(validatedValue, isNullEquivalenceEnabled);
return transformArrayField(validatedValue);
}
case FieldMetadataType.RAW_JSON: {
const validatedValue = validateRawJsonFieldOrThrow(value, key);
return transformRawJsonField(validatedValue, isNullEquivalenceEnabled);
return transformRawJsonField(validatedValue);
}
case FieldMetadataType.RELATION:
case FieldMetadataType.MORPH_RELATION: {
@@ -250,18 +241,18 @@ export class DataArgProcessor {
case FieldMetadataType.EMAILS: {
const validatedValue = validateEmailsFieldOrThrow(value, key);
return transformEmailsValue(validatedValue, isNullEquivalenceEnabled);
return transformEmailsValue(validatedValue);
}
case FieldMetadataType.FULL_NAME: {
const validatedValue = validateFullNameFieldOrThrow(value, key);
return transformFullNameField(validatedValue, isNullEquivalenceEnabled);
return transformFullNameField(validatedValue);
}
case FieldMetadataType.ADDRESS: {
const validatedValue = validateAddressFieldOrThrow(value, key);
return transformAddressField(validatedValue, isNullEquivalenceEnabled);
return transformAddressField(validatedValue);
}
case FieldMetadataType.CURRENCY: {
const validatedValue = validateCurrencyFieldOrThrow(value, key);
@@ -271,7 +262,7 @@ export class DataArgProcessor {
case FieldMetadataType.ACTOR: {
const validatedValue = validateActorFieldOrThrow(value, key);
return transformActorField(validatedValue, isNullEquivalenceEnabled);
return transformActorField(validatedValue);
}
case FieldMetadataType.RICH_TEXT_V2: {
const validatedValue = validateRichTextV2FieldOrThrow(value, key);
@@ -4,18 +4,15 @@ import { transformActorField } from 'src/engine/api/common/common-args-processor
describe('transformActorField', () => {
it('should return null when value is null', () => {
const result = transformActorField(null, true);
const result = transformActorField(null);
expect(result).toBeNull();
});
it('should transform actor with source only', () => {
const result = transformActorField(
{
source: FieldActorSource.EMAIL,
},
true,
);
const result = transformActorField({
source: FieldActorSource.EMAIL,
});
expect(result).toEqual({
source: FieldActorSource.EMAIL,
@@ -23,13 +20,10 @@ describe('transformActorField', () => {
});
it('should transform actor with source and context', () => {
const result = transformActorField(
{
source: FieldActorSource.WORKFLOW,
context: { workflowId: '123', stepId: 'step-1' },
},
true,
);
const result = transformActorField({
source: FieldActorSource.WORKFLOW,
context: { workflowId: '123', stepId: 'step-1' },
});
expect(result).toEqual({
source: FieldActorSource.WORKFLOW,
@@ -38,13 +32,10 @@ describe('transformActorField', () => {
});
it('should transform actor with null source', () => {
const result = transformActorField(
{
source: null,
context: { userId: '456' },
},
true,
);
const result = transformActorField({
source: null,
context: { userId: '456' },
});
expect(result).toEqual({
source: null,
@@ -53,13 +44,10 @@ describe('transformActorField', () => {
});
it('should transform actor with null context', () => {
const result = transformActorField(
{
source: FieldActorSource.API,
context: null,
},
true,
);
const result = transformActorField({
source: FieldActorSource.API,
context: null,
});
expect(result).toEqual({
source: FieldActorSource.API,
@@ -68,13 +56,10 @@ describe('transformActorField', () => {
});
it('should transform empty context object to null', () => {
const result = transformActorField(
{
source: FieldActorSource.EMAIL,
context: {},
},
true,
);
const result = transformActorField({
source: FieldActorSource.EMAIL,
context: {},
});
expect(result).toEqual({
source: FieldActorSource.EMAIL,
@@ -2,25 +2,25 @@ import { transformArrayField } from 'src/engine/api/common/common-args-processor
describe('transformArrayField', () => {
it('should return null when value is null', () => {
const result = transformArrayField(null, true);
const result = transformArrayField(null);
expect(result).toBeNull();
});
it('should return null when value is an empty array', () => {
const result = transformArrayField([], true);
const result = transformArrayField([]);
expect(result).toBeNull();
});
it('should return an array when value is a string', () => {
const result = transformArrayField('singleString', true);
const result = transformArrayField('singleString');
expect(result).toEqual(['singleString']);
});
it('should return an array when value is an array of strings', () => {
const result = transformArrayField(['string1', 'string2', 'string3'], true);
const result = transformArrayField(['string1', 'string2', 'string3']);
expect(result).toEqual(['string1', 'string2', 'string3']);
});
@@ -2,7 +2,7 @@ import { transformFullNameField } from 'src/engine/api/common/common-args-proces
describe('transformFullNameField', () => {
it('should return null when value is null', () => {
const result = transformFullNameField(null, true);
const result = transformFullNameField(null);
expect(result).toBeNull();
});
@@ -12,7 +12,7 @@ describe('transformFullNameField', () => {
firstName: 'John',
lastName: 'Doe',
};
const result = transformFullNameField(value, true);
const result = transformFullNameField(value);
expect(result).toEqual({
firstName: 'John',
@@ -24,7 +24,7 @@ describe('transformFullNameField', () => {
const value = {
lastName: '',
};
const result = transformFullNameField(value, true);
const result = transformFullNameField(value);
expect(result).toEqual({
lastName: null,
@@ -2,19 +2,19 @@ import { transformRawJsonField } from 'src/engine/api/common/common-args-process
describe('transformRawJsonField', () => {
it('should return null when value is null', () => {
const result = transformRawJsonField(null, true);
const result = transformRawJsonField(null);
expect(result).toBeNull();
});
it('should return null when value is empty object', () => {
const result = transformRawJsonField({}, true);
const result = transformRawJsonField({});
expect(result).toBeNull();
});
it('should return the string when value is empty array', () => {
const result = transformRawJsonField([], true);
const result = transformRawJsonField([]);
expect(result).toBeNull();
});
@@ -2,19 +2,19 @@ import { transformTextField } from 'src/engine/api/common/common-args-processors
describe('transformTextField', () => {
it('should return null when value is null', () => {
const result = transformTextField(null, true);
const result = transformTextField(null);
expect(result).toBeNull();
});
it('should return null when value is empty string', () => {
const result = transformTextField('', true);
const result = transformTextField('');
expect(result).toBeNull();
});
it('should return the string when value is a non-empty string', () => {
const result = transformTextField('hello world', true);
const result = transformTextField('hello world');
expect(result).toBe('hello world');
});
@@ -11,7 +11,6 @@ export const transformActorField = (
name?: string | null;
workspaceMemberId?: string | null;
} | null,
isNullEquivalenceEnabled: boolean = false,
): {
source?: FieldActorSource | null;
context?: object | string | null;
@@ -24,10 +23,8 @@ export const transformActorField = (
source: value.source,
context: isUndefined(value.context)
? undefined
: transformRawJsonField(value.context, isNullEquivalenceEnabled),
name: isUndefined(value.name)
? undefined
: transformTextField(value.name, isNullEquivalenceEnabled),
: transformRawJsonField(value.context),
name: isUndefined(value.name) ? undefined : transformTextField(value.name),
workspaceMemberId: isUndefined(value.workspaceMemberId)
? undefined
: value.workspaceMemberId,
@@ -14,7 +14,6 @@ export const transformAddressField = (
addressLat?: number | null;
addressLng?: number | null;
} | null,
isNullEquivalenceEnabled: boolean = false,
): {
addressStreet1?: string | null;
addressStreet2?: string | null;
@@ -30,22 +29,22 @@ export const transformAddressField = (
return {
addressStreet1: isUndefined(value.addressStreet1)
? undefined
: transformTextField(value.addressStreet1, isNullEquivalenceEnabled),
: transformTextField(value.addressStreet1),
addressStreet2: isUndefined(value.addressStreet2)
? undefined
: transformTextField(value.addressStreet2, isNullEquivalenceEnabled),
: transformTextField(value.addressStreet2),
addressCity: isUndefined(value.addressCity)
? undefined
: transformTextField(value.addressCity, isNullEquivalenceEnabled),
: transformTextField(value.addressCity),
addressState: isUndefined(value.addressState)
? undefined
: transformTextField(value.addressState, isNullEquivalenceEnabled),
: transformTextField(value.addressState),
addressPostcode: isUndefined(value.addressPostcode)
? undefined
: transformTextField(value.addressPostcode, isNullEquivalenceEnabled),
: transformTextField(value.addressPostcode),
addressCountry: isUndefined(value.addressCountry)
? undefined
: transformTextField(value.addressCountry, isNullEquivalenceEnabled),
: transformTextField(value.addressCountry),
addressLat: isUndefined(value.addressLat)
? undefined
: transformNumericField(value.addressLat),
@@ -2,11 +2,8 @@ import { isNullEquivalentArrayFieldValue } from 'src/engine/api/common/common-ar
export const transformArrayField = (
value: string | string[] | null,
isNullEquivalenceEnabled: boolean = false,
): string[] | null => {
if (typeof value === 'string') return [value];
return isNullEquivalenceEnabled && isNullEquivalentArrayFieldValue(value)
? null
: value;
return isNullEquivalentArrayFieldValue(value) ? null : value;
};
@@ -8,7 +8,6 @@ export const transformCurrencyField = (
amountMicros?: number | string | null;
currencyCode?: string | null;
} | null,
isNullEquivalenceEnabled: boolean = false,
): {
amountMicros?: number | null;
currencyCode?: string | null;
@@ -21,6 +20,6 @@ export const transformCurrencyField = (
: transformNumericField(value.amountMicros),
currencyCode: isUndefined(value.currencyCode)
? undefined
: transformTextField(value.currencyCode, isNullEquivalenceEnabled),
: transformTextField(value.currencyCode),
};
};
@@ -7,7 +7,6 @@ export const transformFullNameField = (
firstName?: string | null;
lastName?: string | null;
} | null,
isNullEquivalenceEnabled: boolean = false,
): {
firstName?: string | null;
lastName?: string | null;
@@ -17,9 +16,9 @@ export const transformFullNameField = (
return {
firstName: isUndefined(value.firstName)
? undefined
: transformTextField(value.firstName, isNullEquivalenceEnabled),
: transformTextField(value.firstName),
lastName: isUndefined(value.lastName)
? undefined
: transformTextField(value.lastName, isNullEquivalenceEnabled),
: transformTextField(value.lastName),
};
};
@@ -3,9 +3,6 @@ import { isNullEquivalentRawJsonFieldValue } from 'src/engine/api/common/common-
export const transformRawJsonField = (
value: object | string | null,
isNullEquivalenceEnabled: boolean = false,
): object | string | null => {
return isNullEquivalenceEnabled && isNullEquivalentRawJsonFieldValue(value)
? null
: value;
return isNullEquivalentRawJsonFieldValue(value) ? null : value;
};
@@ -1,10 +1,5 @@
import { isNullEquivalentTextFieldValue } from 'src/engine/api/common/common-args-processors/data-arg-processor/utils/is-null-equivalent-text-field-value.util';
export const transformTextField = (
value: string | null,
isNullEquivalenceEnabled: boolean = false,
): string | null => {
return isNullEquivalenceEnabled && isNullEquivalentTextFieldValue(value)
? null
: value;
export const transformTextField = (value: string | null): string | null => {
return isNullEquivalentTextFieldValue(value) ? null : value;
};
@@ -15,5 +15,4 @@ 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',
}
@@ -16,7 +16,6 @@ import { getCompositeTypeOrThrow } from 'src/engine/metadata-modules/field-metad
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { buildFieldMapsFromFlatObjectMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/build-field-maps-from-flat-object-metadata.util';
import { computeUniqueIndexWhereClause } from 'src/engine/metadata-modules/index-metadata/utils/compute-unique-index-where-clause.util';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
@Injectable()
@@ -148,17 +147,6 @@ 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);
const restrictedFields =
repository.objectRecordsPermissions?.[flatObjectMetadata.id]
?.restrictedFields;
@@ -173,10 +161,6 @@ export class UpsertRecordService {
transformedObjectRecord,
{
conflictPaths: conflictPaths,
indexPredicate:
indexPredicate.length > 0
? `${indexPredicate.join(' AND ')}`
: undefined,
},
undefined,
selectedColumns,
@@ -1,9 +1,8 @@
import { isNonEmptyString } from '@sniptt/guards';
import { isNonEmptyArray, isNonEmptyString } from '@sniptt/guards';
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) {
@@ -13,9 +12,7 @@ export const transformEmailsValue = (
let additionalEmails: string | null = value?.additionalEmails;
const primaryEmail = value?.primaryEmail
? value.primaryEmail.toLowerCase()
: isNullEquivalenceEnabled
? null
: '';
: null;
if (additionalEmails) {
try {
@@ -25,16 +22,9 @@ export const transformEmailsValue = (
: additionalEmails
) as string[];
additionalEmails = JSON.stringify(
emailArray.map((email) => email.toLowerCase()),
);
if (isNullEquivalenceEnabled) {
additionalEmails =
Array.isArray(emailArray) && emailArray.length === 0
? null
: additionalEmails;
}
additionalEmails = isNonEmptyArray(emailArray)
? JSON.stringify(emailArray.map((email) => email.toLowerCase()))
: null;
} catch {
/* empty */
}
@@ -1,79 +0,0 @@
import { isNonEmptyString } from '@sniptt/guards';
import {
FieldMetadataType,
compositeTypeDefinitions,
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import {
FieldMetadataException,
FieldMetadataExceptionCode,
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
import {
IndexMetadataException,
IndexMetadataExceptionCode,
} from 'src/engine/metadata-modules/index-metadata/index-field-metadata.exception';
//TODO : To delete once IS_NULL_EQUIVALENCE_ENABLED feature flag removed
export const computeUniqueIndexWhereClause = (
fieldMetadata: Pick<FieldMetadataEntity, 'type' | 'name' | 'defaultValue'>,
) => {
const defaultValue = fieldMetadata.defaultValue;
if (!isDefined(defaultValue)) return;
if (
fieldMetadata.type === FieldMetadataType.RELATION ||
fieldMetadata.type === FieldMetadataType.MORPH_RELATION
) {
throw new IndexMetadataException(
`Unique index cannot be created for relation or morph relation field ${fieldMetadata.name}`,
IndexMetadataExceptionCode.INDEX_NOT_SUPPORTED_FOR_MORH_RELATION_FIELD_AND_RELATION_FIELD,
);
}
if (!isCompositeFieldMetadataType(fieldMetadata.type)) {
return `"${fieldMetadata.name}" != ${defaultValue}`;
}
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
if (!isDefined(compositeType)) {
throw new FieldMetadataException(
`Composite type not found for field metadata type: ${fieldMetadata.type}`,
FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR,
);
}
const defaultDefaultValueProperties = Object.keys(defaultValue);
const columnNamesWithDefaultValues = compositeType.properties
.filter(
(property) =>
property.isIncludedInUniqueConstraint &&
defaultDefaultValueProperties.includes(property.name),
)
.map((property) => {
const defaultValueProperty =
defaultValue[property.name as keyof typeof defaultValue];
if (isNonEmptyString(defaultValueProperty)) {
return [
computeCompositeColumnName(fieldMetadata, property),
defaultValueProperty,
];
}
})
.filter(isDefined);
return columnNamesWithDefaultValues.length > 0
? columnNamesWithDefaultValues
.map(
([columnName, defaultValue]) => `"${columnName}" != ${defaultValue}`,
)
.join(' OR ')
: undefined;
};
@@ -207,7 +207,6 @@ describe('WorkspaceEntityManager', () => {
IS_WORKFLOW_RUN_STOPPAGE_ENABLED: false,
IS_DASHBOARD_V2_ENABLED: false,
IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED: false,
IS_NULL_EQUIVALENCE_ENABLED: false,
},
eventEmitterService: {
emitMutationEvent: jest.fn(),
@@ -234,7 +233,6 @@ describe('WorkspaceEntityManager', () => {
IS_WORKFLOW_RUN_STOPPAGE_ENABLED: false,
IS_DASHBOARD_V2_ENABLED: false,
IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED: false,
IS_NULL_EQUIVALENCE_ENABLED: false,
},
permissionsPerRoleId: {},
} as WorkspaceDataSource;
@@ -92,11 +92,6 @@ export const seedFeatureFlags = async ({
workspaceId: workspaceId,
value: true,
},
{
key: FeatureFlagKey.IS_NULL_EQUIVALENCE_ENABLED,
workspaceId: workspaceId,
value: true,
},
])
.execute();
};
@@ -2,5 +2,4 @@ import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/featu
export const DEFAULT_FEATURE_FLAGS = [
FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
FeatureFlagKey.IS_NULL_EQUIVALENCE_ENABLED,
] as const satisfies FeatureFlagKey[];