Remove old relations (#11993)

This is a first PR to remove old relation logic

Next steps:
- remove relationMetadata from cache
- remove relationMetadata table content and structure
- refactor relationDefinition to leverage field.settings instead
This commit is contained in:
Charles Bochet
2025-05-13 11:28:22 +02:00
committed by GitHub
parent 9ed6edc005
commit 45d4845b26
63 changed files with 223 additions and 2016 deletions

View File

@ -656,7 +656,6 @@ export enum FeatureFlagKey {
IsCopilotEnabled = 'IsCopilotEnabled', IsCopilotEnabled = 'IsCopilotEnabled',
IsCustomDomainEnabled = 'IsCustomDomainEnabled', IsCustomDomainEnabled = 'IsCustomDomainEnabled',
IsJsonFilterEnabled = 'IsJsonFilterEnabled', IsJsonFilterEnabled = 'IsJsonFilterEnabled',
IsNewRelationEnabled = 'IsNewRelationEnabled',
IsPermissionsV2Enabled = 'IsPermissionsV2Enabled', IsPermissionsV2Enabled = 'IsPermissionsV2Enabled',
IsPostgreSQLIntegrationEnabled = 'IsPostgreSQLIntegrationEnabled', IsPostgreSQLIntegrationEnabled = 'IsPostgreSQLIntegrationEnabled',
IsStripeIntegrationEnabled = 'IsStripeIntegrationEnabled', IsStripeIntegrationEnabled = 'IsStripeIntegrationEnabled',

View File

@ -587,7 +587,6 @@ export enum FeatureFlagKey {
IsCopilotEnabled = 'IsCopilotEnabled', IsCopilotEnabled = 'IsCopilotEnabled',
IsCustomDomainEnabled = 'IsCustomDomainEnabled', IsCustomDomainEnabled = 'IsCustomDomainEnabled',
IsJsonFilterEnabled = 'IsJsonFilterEnabled', IsJsonFilterEnabled = 'IsJsonFilterEnabled',
IsNewRelationEnabled = 'IsNewRelationEnabled',
IsPermissionsV2Enabled = 'IsPermissionsV2Enabled', IsPermissionsV2Enabled = 'IsPermissionsV2Enabled',
IsPostgreSQLIntegrationEnabled = 'IsPostgreSQLIntegrationEnabled', IsPostgreSQLIntegrationEnabled = 'IsPostgreSQLIntegrationEnabled',
IsStripeIntegrationEnabled = 'IsStripeIntegrationEnabled', IsStripeIntegrationEnabled = 'IsStripeIntegrationEnabled',

View File

@ -9,11 +9,11 @@ import {
ActiveOrSuspendedWorkspacesMigrationCommandRunner, ActiveOrSuspendedWorkspacesMigrationCommandRunner,
RunOnWorkspaceArgs, RunOnWorkspaceArgs,
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner'; } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
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 { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
@Command({ @Command({
name: 'upgrade:0-53:remove-relation-foreign-key-field-metadata', name: 'upgrade:0-53:remove-relation-foreign-key-field-metadata',
@ -67,7 +67,7 @@ export class RemoveRelationForeignKeyFieldMetadataCommand extends ActiveOrSuspen
); );
} else { } else {
await this.featureFlagService.enableFeatureFlags( await this.featureFlagService.enableFeatureFlags(
[FeatureFlagKey.IsNewRelationEnabled], ['IS_NEW_RELATION_ENABLED' as FeatureFlagKey],
workspaceId, workspaceId,
); );
await this.fieldMetadataRepository.delete({ await this.fieldMetadataRepository.delete({

View File

@ -45,11 +45,6 @@ export const seedFeatureFlags = async (
workspaceId: workspaceId, workspaceId: workspaceId,
value: false, value: false,
}, },
{
key: FeatureFlagKey.IsNewRelationEnabled,
workspaceId: workspaceId,
value: true,
},
]) ])
.execute(); .execute();
}; };

View File

@ -6,7 +6,6 @@ import {
} from 'typeorm'; } from 'typeorm';
import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface'; import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
import { FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map'; import { FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map';
@ -20,14 +19,12 @@ export class GraphqlQueryFilterConditionParser {
constructor( constructor(
fieldMetadataMapByName: FieldMetadataMap, fieldMetadataMapByName: FieldMetadataMap,
fieldMetadataMapByJoinColumnName: FieldMetadataMap, fieldMetadataMapByJoinColumnName: FieldMetadataMap,
featureFlagsMap: FeatureFlagMap,
) { ) {
this.fieldMetadataMapByName = fieldMetadataMapByName; this.fieldMetadataMapByName = fieldMetadataMapByName;
this.fieldMetadataMapByJoinColumnName = fieldMetadataMapByJoinColumnName; this.fieldMetadataMapByJoinColumnName = fieldMetadataMapByJoinColumnName;
this.queryFilterFieldParser = new GraphqlQueryFilterFieldParser( this.queryFilterFieldParser = new GraphqlQueryFilterFieldParser(
this.fieldMetadataMapByName, this.fieldMetadataMapByName,
this.fieldMetadataMapByJoinColumnName, this.fieldMetadataMapByJoinColumnName,
featureFlagsMap,
); );
} }

View File

@ -2,7 +2,6 @@ import { capitalize } from 'twenty-shared/utils';
import { WhereExpressionBuilder } from 'typeorm'; import { WhereExpressionBuilder } from 'typeorm';
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
import { import {
GraphqlQueryRunnerException, GraphqlQueryRunnerException,
@ -19,16 +18,13 @@ const ARRAY_OPERATORS = ['in', 'contains', 'notContains'];
export class GraphqlQueryFilterFieldParser { export class GraphqlQueryFilterFieldParser {
private fieldMetadataMapByName: FieldMetadataMap; private fieldMetadataMapByName: FieldMetadataMap;
private fieldMetadataMapByJoinColumnName: FieldMetadataMap; private fieldMetadataMapByJoinColumnName: FieldMetadataMap;
private featureFlagsMap: FeatureFlagMap;
constructor( constructor(
fieldMetadataMapByName: FieldMetadataMap, fieldMetadataMapByName: FieldMetadataMap,
fieldMetadataMapByJoinColumnName: FieldMetadataMap, fieldMetadataMapByJoinColumnName: FieldMetadataMap,
featureFlagsMap: FeatureFlagMap,
) { ) {
this.fieldMetadataMapByName = fieldMetadataMapByName; this.fieldMetadataMapByName = fieldMetadataMapByName;
this.fieldMetadataMapByJoinColumnName = fieldMetadataMapByJoinColumnName; this.fieldMetadataMapByJoinColumnName = fieldMetadataMapByJoinColumnName;
this.featureFlagsMap = featureFlagsMap;
} }
public parse( public parse(

View File

@ -1,25 +1,17 @@
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
import { import {
GraphqlQuerySelectedFieldsParser, GraphqlQuerySelectedFieldsParser,
GraphqlQuerySelectedFieldsResult, GraphqlQuerySelectedFieldsResult,
} from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields.parser'; } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields.parser';
import { getRelationObjectMetadata } from 'src/engine/api/graphql/graphql-query-runner/utils/get-relation-object-metadata.util';
import { getTargetObjectMetadataOrThrow } from 'src/engine/api/graphql/graphql-query-runner/utils/get-target-object-metadata.util'; import { getTargetObjectMetadataOrThrow } from 'src/engine/api/graphql/graphql-query-runner/utils/get-target-object-metadata.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
export class GraphqlQuerySelectedFieldsRelationParser { export class GraphqlQuerySelectedFieldsRelationParser {
private objectMetadataMaps: ObjectMetadataMaps; private objectMetadataMaps: ObjectMetadataMaps;
private featureFlagsMap: FeatureFlagMap;
constructor( constructor(objectMetadataMaps: ObjectMetadataMaps) {
objectMetadataMaps: ObjectMetadataMaps,
featureFlagsMap: FeatureFlagMap,
) {
this.objectMetadataMaps = objectMetadataMaps; this.objectMetadataMaps = objectMetadataMaps;
this.featureFlagsMap = featureFlagsMap;
} }
parseRelationField( parseRelationField(
@ -34,17 +26,14 @@ export class GraphqlQuerySelectedFieldsRelationParser {
accumulator.relations[fieldKey] = true; accumulator.relations[fieldKey] = true;
const isNewRelationEnabled = const targetObjectMetadata = getTargetObjectMetadataOrThrow(
this.featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled]; fieldMetadata,
this.objectMetadataMaps,
const targetObjectMetadata = isNewRelationEnabled );
? getTargetObjectMetadataOrThrow(fieldMetadata, this.objectMetadataMaps)
: getRelationObjectMetadata(fieldMetadata, this.objectMetadataMaps);
const targetFields = targetObjectMetadata.fieldsByName; const targetFields = targetObjectMetadata.fieldsByName;
const fieldParser = new GraphqlQuerySelectedFieldsParser( const fieldParser = new GraphqlQuerySelectedFieldsParser(
this.objectMetadataMaps, this.objectMetadataMaps,
this.featureFlagsMap,
); );
const relationAccumulator = fieldParser.parse(fieldValue, targetFields); const relationAccumulator = fieldParser.parse(fieldValue, targetFields);

View File

@ -1,6 +1,5 @@
import { capitalize } from 'twenty-shared/utils'; import { capitalize } from 'twenty-shared/utils';
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
import { GraphqlQuerySelectedFieldsAggregateParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields-aggregate.parser'; import { GraphqlQuerySelectedFieldsAggregateParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields-aggregate.parser';
@ -21,15 +20,9 @@ export class GraphqlQuerySelectedFieldsParser {
private graphqlQuerySelectedFieldsRelationParser: GraphqlQuerySelectedFieldsRelationParser; private graphqlQuerySelectedFieldsRelationParser: GraphqlQuerySelectedFieldsRelationParser;
private aggregateParser: GraphqlQuerySelectedFieldsAggregateParser; private aggregateParser: GraphqlQuerySelectedFieldsAggregateParser;
constructor( constructor(objectMetadataMaps: ObjectMetadataMaps) {
objectMetadataMaps: ObjectMetadataMaps,
featureFlagsMap: FeatureFlagMap,
) {
this.graphqlQuerySelectedFieldsRelationParser = this.graphqlQuerySelectedFieldsRelationParser =
new GraphqlQuerySelectedFieldsRelationParser( new GraphqlQuerySelectedFieldsRelationParser(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
this.aggregateParser = new GraphqlQuerySelectedFieldsAggregateParser(); this.aggregateParser = new GraphqlQuerySelectedFieldsAggregateParser();
} }

View File

@ -9,8 +9,11 @@ import {
ObjectRecordFilter, ObjectRecordFilter,
ObjectRecordOrderBy, ObjectRecordOrderBy,
} from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface'; } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
import {
GraphqlQueryRunnerException,
GraphqlQueryRunnerExceptionCode,
} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
import { GraphqlQueryFilterConditionParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-condition.parser'; import { GraphqlQueryFilterConditionParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-condition.parser';
import { GraphqlQueryOrderFieldParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-order/graphql-query-order.parser'; import { GraphqlQueryOrderFieldParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-order/graphql-query-order.parser';
import { import {
@ -21,10 +24,6 @@ import { FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metada
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { getObjectMetadataMapItemByNameSingular } from 'src/engine/metadata-modules/utils/get-object-metadata-map-item-by-name-singular.util'; import { getObjectMetadataMapItemByNameSingular } from 'src/engine/metadata-modules/utils/get-object-metadata-map-item-by-name-singular.util';
import {
GraphqlQueryRunnerException,
GraphqlQueryRunnerExceptionCode,
} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
export class GraphqlQueryParser { export class GraphqlQueryParser {
private fieldMetadataMapByName: FieldMetadataMap; private fieldMetadataMapByName: FieldMetadataMap;
@ -32,22 +31,18 @@ export class GraphqlQueryParser {
private objectMetadataMaps: ObjectMetadataMaps; private objectMetadataMaps: ObjectMetadataMaps;
private filterConditionParser: GraphqlQueryFilterConditionParser; private filterConditionParser: GraphqlQueryFilterConditionParser;
private orderFieldParser: GraphqlQueryOrderFieldParser; private orderFieldParser: GraphqlQueryOrderFieldParser;
private featureFlagsMap: FeatureFlagMap;
constructor( constructor(
fieldMetadataMapByName: FieldMetadataMap, fieldMetadataMapByName: FieldMetadataMap,
fieldMetadataMapByJoinColumnName: FieldMetadataMap, fieldMetadataMapByJoinColumnName: FieldMetadataMap,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
featureFlagsMap: FeatureFlagMap,
) { ) {
this.objectMetadataMaps = objectMetadataMaps; this.objectMetadataMaps = objectMetadataMaps;
this.fieldMetadataMapByName = fieldMetadataMapByName; this.fieldMetadataMapByName = fieldMetadataMapByName;
this.fieldMetadataMapByJoinColumnName = fieldMetadataMapByJoinColumnName; this.fieldMetadataMapByJoinColumnName = fieldMetadataMapByJoinColumnName;
this.featureFlagsMap = featureFlagsMap;
this.filterConditionParser = new GraphqlQueryFilterConditionParser( this.filterConditionParser = new GraphqlQueryFilterConditionParser(
this.fieldMetadataMapByName, this.fieldMetadataMapByName,
this.fieldMetadataMapByJoinColumnName, this.fieldMetadataMapByJoinColumnName,
featureFlagsMap,
); );
this.orderFieldParser = new GraphqlQueryOrderFieldParser( this.orderFieldParser = new GraphqlQueryOrderFieldParser(
this.fieldMetadataMapByName, this.fieldMetadataMapByName,
@ -136,7 +131,6 @@ export class GraphqlQueryParser {
const selectedFieldsParser = new GraphqlQuerySelectedFieldsParser( const selectedFieldsParser = new GraphqlQuerySelectedFieldsParser(
this.objectMetadataMaps, this.objectMetadataMaps,
this.featureFlagsMap,
); );
return selectedFieldsParser.parse(graphqlSelectedFields, parentFields); return selectedFieldsParser.parse(graphqlSelectedFields, parentFields);

View File

@ -6,7 +6,6 @@ import {
ObjectRecordOrderBy, ObjectRecordOrderBy,
} from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface'; } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
import { IConnection } from 'src/engine/api/graphql/workspace-query-runner/interfaces/connection.interface'; import { IConnection } from 'src/engine/api/graphql/workspace-query-runner/interfaces/connection.interface';
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
import { CONNECTION_MAX_DEPTH } from 'src/engine/api/graphql/graphql-query-runner/constants/connection-max-depth.constant'; import { CONNECTION_MAX_DEPTH } from 'src/engine/api/graphql/graphql-query-runner/constants/connection-max-depth.constant';
@ -15,10 +14,8 @@ import {
GraphqlQueryRunnerExceptionCode, GraphqlQueryRunnerExceptionCode,
} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
import { encodeCursor } from 'src/engine/api/graphql/graphql-query-runner/utils/cursors.util'; import { encodeCursor } from 'src/engine/api/graphql/graphql-query-runner/utils/cursors.util';
import { getRelationObjectMetadata } from 'src/engine/api/graphql/graphql-query-runner/utils/get-relation-object-metadata.util';
import { getTargetObjectMetadataOrThrow } from 'src/engine/api/graphql/graphql-query-runner/utils/get-target-object-metadata.util'; import { getTargetObjectMetadataOrThrow } from 'src/engine/api/graphql/graphql-query-runner/utils/get-target-object-metadata.util';
import { AggregationField } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-available-aggregations-from-object-fields.util'; import { AggregationField } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-available-aggregations-from-object-fields.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
@ -29,14 +26,9 @@ import { isPlainObject } from 'src/utils/is-plain-object';
export class ObjectRecordsToGraphqlConnectionHelper { export class ObjectRecordsToGraphqlConnectionHelper {
private objectMetadataMaps: ObjectMetadataMaps; private objectMetadataMaps: ObjectMetadataMaps;
private featureFlagsMap: FeatureFlagMap;
constructor( constructor(objectMetadataMaps: ObjectMetadataMaps) {
objectMetadataMaps: ObjectMetadataMaps,
featureFlagsMap: FeatureFlagMap,
) {
this.objectMetadataMaps = objectMetadataMaps; this.objectMetadataMaps = objectMetadataMaps;
this.featureFlagsMap = featureFlagsMap;
} }
public createConnection<T extends ObjectRecord = ObjectRecord>({ public createConnection<T extends ObjectRecord = ObjectRecord>({
@ -154,9 +146,6 @@ export class ObjectRecordsToGraphqlConnectionHelper {
); );
} }
const isNewRelationEnabled =
this.featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled];
const objectMetadata = getObjectMetadataMapItemByNameSingular( const objectMetadata = getObjectMetadataMapItemByNameSingular(
this.objectMetadataMaps, this.objectMetadataMaps,
objectName, objectName,
@ -181,12 +170,10 @@ export class ObjectRecordsToGraphqlConnectionHelper {
if (isRelationFieldMetadataType(fieldMetadata.type)) { if (isRelationFieldMetadataType(fieldMetadata.type)) {
if (Array.isArray(value)) { if (Array.isArray(value)) {
const targetObjectMetadata = isNewRelationEnabled const targetObjectMetadata = getTargetObjectMetadataOrThrow(
? getTargetObjectMetadataOrThrow( fieldMetadata,
fieldMetadata, this.objectMetadataMaps,
this.objectMetadataMaps, );
)
: getRelationObjectMetadata(fieldMetadata, this.objectMetadataMaps);
processedObjectRecord[key] = this.createConnection({ processedObjectRecord[key] = this.createConnection({
objectRecords: value, objectRecords: value,
@ -206,12 +193,10 @@ export class ObjectRecordsToGraphqlConnectionHelper {
depth: depth + 1, depth: depth + 1,
}); });
} else if (isPlainObject(value)) { } else if (isPlainObject(value)) {
const targetObjectMetadata = isNewRelationEnabled const targetObjectMetadata = getTargetObjectMetadataOrThrow(
? getTargetObjectMetadataOrThrow( fieldMetadata,
fieldMetadata, this.objectMetadataMaps,
this.objectMetadataMaps, );
)
: getRelationObjectMetadata(fieldMetadata, this.objectMetadataMaps);
processedObjectRecord[key] = this.processRecord({ processedObjectRecord[key] = this.processRecord({
objectRecord: value, objectRecord: value,

View File

@ -324,7 +324,6 @@ export class ProcessNestedRelationsV2Helper {
result, result,
targetObjectMetadata, targetObjectMetadata,
objectMetadataMaps, objectMetadataMaps,
true,
); );
return { relationResults, relationAggregatedFieldsResult }; return { relationResults, relationAggregatedFieldsResult };

View File

@ -1,32 +1,16 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { import { FindOptionsRelations, ObjectLiteral } from 'typeorm';
DataSource,
FindOptionsRelations,
ObjectLiteral,
SelectQueryBuilder,
} from 'typeorm';
import { ObjectRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface'; import { ObjectRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
import {
GraphqlQueryRunnerException,
GraphqlQueryRunnerExceptionCode,
} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
import { ProcessAggregateHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-aggregate.helper'; import { ProcessAggregateHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-aggregate.helper';
import { ProcessNestedRelationsV2Helper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations-v2.helper'; import { ProcessNestedRelationsV2Helper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations-v2.helper';
import {
getRelationMetadata,
getRelationObjectMetadata,
} from 'src/engine/api/graphql/graphql-query-runner/utils/get-relation-object-metadata.util';
import { AggregationField } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-available-aggregations-from-object-fields.util'; import { AggregationField } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-available-aggregations-from-object-fields.util';
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { getObjectMetadataMapItemByNameSingular } from 'src/engine/metadata-modules/utils/get-object-metadata-map-item-by-name-singular.util';
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource'; import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
import { deduceRelationDirection } from 'src/engine/utils/deduce-relation-direction.util';
@Injectable() @Injectable()
export class ProcessNestedRelationsHelper { export class ProcessNestedRelationsHelper {
@ -45,7 +29,6 @@ export class ProcessNestedRelationsHelper {
limit, limit,
authContext, authContext,
dataSource, dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks, shouldBypassPermissionChecks,
roleId, roleId,
}: { }: {
@ -58,472 +41,21 @@ export class ProcessNestedRelationsHelper {
limit: number; limit: number;
authContext: AuthContext; authContext: AuthContext;
dataSource: WorkspaceDataSource; dataSource: WorkspaceDataSource;
isNewRelationEnabled: boolean;
shouldBypassPermissionChecks: boolean; shouldBypassPermissionChecks: boolean;
roleId?: string; roleId?: string;
}): Promise<void> { }): Promise<void> {
if (isNewRelationEnabled) { return this.processNestedRelationsV2Helper.processNestedRelations({
return this.processNestedRelationsV2Helper.processNestedRelations({
objectMetadataMaps,
parentObjectMetadataItem,
parentObjectRecords,
parentObjectRecordsAggregatedValues,
relations,
aggregate,
limit,
authContext,
dataSource,
shouldBypassPermissionChecks,
roleId,
});
}
const processRelationTasks = Object.entries(relations).map(
([relationName, nestedRelations]) =>
this.processRelation({
objectMetadataMaps,
parentObjectMetadataItem,
parentObjectRecords,
parentObjectRecordsAggregatedValues,
relationName,
nestedRelations,
aggregate,
limit,
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
}),
);
await Promise.all(processRelationTasks);
}
private async processRelation<T extends ObjectRecord = ObjectRecord>({
objectMetadataMaps,
parentObjectMetadataItem,
parentObjectRecords,
parentObjectRecordsAggregatedValues,
relationName,
nestedRelations,
aggregate,
limit,
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
}: {
objectMetadataMaps: ObjectMetadataMaps;
parentObjectMetadataItem: ObjectMetadataItemWithFieldMaps;
parentObjectRecords: T[];
parentObjectRecordsAggregatedValues: Record<string, any>;
relationName: string;
nestedRelations: any;
aggregate: Record<string, AggregationField>;
limit: number;
authContext: AuthContext;
dataSource: DataSource;
isNewRelationEnabled: boolean;
shouldBypassPermissionChecks: boolean;
roleId?: string;
}): Promise<void> {
const relationFieldMetadata =
parentObjectMetadataItem.fieldsByName[relationName];
const relationMetadata = getRelationMetadata(relationFieldMetadata);
const relationDirection = deduceRelationDirection(
relationFieldMetadata,
relationMetadata,
);
const processor =
relationDirection === 'to'
? this.processToRelation
: this.processFromRelation;
await processor.call(this, {
objectMetadataMaps, objectMetadataMaps,
parentObjectMetadataItem, parentObjectMetadataItem,
parentObjectRecords, parentObjectRecords,
parentObjectRecordsAggregatedValues, parentObjectRecordsAggregatedValues,
relationName, relations,
nestedRelations,
aggregate, aggregate,
limit, limit,
authContext, authContext,
dataSource, dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks, shouldBypassPermissionChecks,
roleId, roleId,
}); });
} }
private async processFromRelation<T extends ObjectRecord = ObjectRecord>({
objectMetadataMaps,
parentObjectMetadataItem,
parentObjectRecords,
parentObjectRecordsAggregatedValues,
relationName,
nestedRelations,
aggregate,
limit,
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
}: {
objectMetadataMaps: ObjectMetadataMaps;
parentObjectMetadataItem: ObjectMetadataItemWithFieldMaps;
parentObjectRecords: T[];
parentObjectRecordsAggregatedValues: Record<string, any>;
relationName: string;
nestedRelations: any;
aggregate: Record<string, AggregationField>;
limit: number;
authContext: AuthContext;
dataSource: WorkspaceDataSource;
isNewRelationEnabled: boolean;
shouldBypassPermissionChecks: boolean;
roleId?: string;
}): Promise<void> {
const { inverseRelationName, referenceObjectMetadata } =
this.getRelationMetadata({
objectMetadataMaps,
parentObjectMetadataItem,
relationName,
});
const relationRepository = dataSource.getRepository(
referenceObjectMetadata.nameSingular,
shouldBypassPermissionChecks,
roleId,
);
const referenceQueryBuilder = relationRepository.createQueryBuilder(
referenceObjectMetadata.nameSingular,
);
const relationIds = this.getUniqueIds({
records: parentObjectRecords,
idField: 'id',
});
const { relationResults, relationAggregatedFieldsResult } =
await this.findRelations({
referenceQueryBuilder,
column: `"${inverseRelationName}Id"`,
ids: relationIds,
limit: limit * parentObjectRecords.length,
objectMetadataMaps,
referenceObjectMetadata,
aggregate,
relationName,
});
this.assignFromRelationResults({
parentRecords: parentObjectRecords,
parentObjectRecordsAggregatedValues,
relationResults,
relationAggregatedFieldsResult,
relationName,
joinField: `${inverseRelationName}Id`,
});
const referenceObjectMetadataItemWithFieldsMaps =
getObjectMetadataMapItemByNameSingular(
objectMetadataMaps,
referenceObjectMetadata.nameSingular,
);
if (!referenceObjectMetadataItemWithFieldsMaps) {
throw new GraphqlQueryRunnerException(
`Object ${referenceObjectMetadata.nameSingular} not found`,
GraphqlQueryRunnerExceptionCode.OBJECT_METADATA_NOT_FOUND,
);
}
if (Object.keys(nestedRelations).length > 0) {
await this.processNestedRelations({
objectMetadataMaps,
parentObjectMetadataItem: referenceObjectMetadataItemWithFieldsMaps,
parentObjectRecords: relationResults as ObjectRecord[],
parentObjectRecordsAggregatedValues: relationAggregatedFieldsResult,
relations: nestedRelations as Record<
string,
FindOptionsRelations<ObjectLiteral>
>,
aggregate,
limit,
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
});
}
}
private async processToRelation<T extends ObjectRecord = ObjectRecord>({
objectMetadataMaps,
parentObjectMetadataItem,
parentObjectRecords,
parentObjectRecordsAggregatedValues,
relationName,
nestedRelations,
aggregate,
limit,
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
}: {
objectMetadataMaps: ObjectMetadataMaps;
parentObjectMetadataItem: ObjectMetadataItemWithFieldMaps;
parentObjectRecords: T[];
parentObjectRecordsAggregatedValues: Record<string, any>;
relationName: string;
nestedRelations: any;
aggregate: Record<string, AggregationField>;
limit: number;
authContext: any;
dataSource: WorkspaceDataSource;
isNewRelationEnabled: boolean;
shouldBypassPermissionChecks: boolean;
roleId?: string;
}): Promise<void> {
const { referenceObjectMetadata } = this.getRelationMetadata({
objectMetadataMaps,
parentObjectMetadataItem,
relationName,
});
const relationRepository = dataSource.getRepository(
referenceObjectMetadata.nameSingular,
shouldBypassPermissionChecks,
roleId,
);
const referenceQueryBuilder = relationRepository.createQueryBuilder(
referenceObjectMetadata.nameSingular,
);
const relationIds = this.getUniqueIds({
records: parentObjectRecords,
idField: `${relationName}Id`,
});
const { relationResults, relationAggregatedFieldsResult } =
await this.findRelations({
referenceQueryBuilder,
column: 'id',
ids: relationIds,
limit,
objectMetadataMaps,
referenceObjectMetadata,
aggregate,
relationName,
});
this.assignToRelationResults({
parentRecords: parentObjectRecords,
parentObjectRecordsAggregatedValues: parentObjectRecordsAggregatedValues,
relationResults,
relationAggregatedFieldsResult,
relationName,
});
const referenceObjectMetadataItemWithFieldsMaps =
getObjectMetadataMapItemByNameSingular(
objectMetadataMaps,
referenceObjectMetadata.nameSingular,
);
if (!referenceObjectMetadataItemWithFieldsMaps) {
throw new GraphqlQueryRunnerException(
`Object ${referenceObjectMetadata.nameSingular} not found`,
GraphqlQueryRunnerExceptionCode.OBJECT_METADATA_NOT_FOUND,
);
}
if (Object.keys(nestedRelations).length > 0) {
await this.processNestedRelations({
objectMetadataMaps,
parentObjectMetadataItem: referenceObjectMetadataItemWithFieldsMaps,
parentObjectRecords: relationResults as ObjectRecord[],
parentObjectRecordsAggregatedValues: relationAggregatedFieldsResult,
relations: nestedRelations as Record<
string,
FindOptionsRelations<ObjectLiteral>
>,
aggregate,
limit,
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
});
}
}
private getRelationMetadata({
objectMetadataMaps,
parentObjectMetadataItem,
relationName,
}: {
objectMetadataMaps: ObjectMetadataMaps;
parentObjectMetadataItem: ObjectMetadataItemWithFieldMaps;
relationName: string;
}) {
const relationFieldMetadata =
parentObjectMetadataItem.fieldsByName[relationName];
const relationMetadata = getRelationMetadata(relationFieldMetadata);
const referenceObjectMetadata = getRelationObjectMetadata(
relationFieldMetadata,
objectMetadataMaps,
);
const inverseRelationName =
objectMetadataMaps.byId[relationMetadata.toObjectMetadataId]?.fieldsById[
relationMetadata.toFieldMetadataId
]?.name;
return { inverseRelationName, referenceObjectMetadata };
}
private getUniqueIds({
records,
idField,
}: {
records: ObjectRecord[];
idField: string;
}): any[] {
return [...new Set(records.map((item) => item[idField]))];
}
private async findRelations({
referenceQueryBuilder,
column,
ids,
limit,
objectMetadataMaps,
referenceObjectMetadata,
aggregate,
relationName,
}: {
referenceQueryBuilder: SelectQueryBuilder<any>;
column: string;
ids: any[];
limit: number;
objectMetadataMaps: ObjectMetadataMaps;
referenceObjectMetadata: ObjectMetadataItemWithFieldMaps;
aggregate: Record<string, any>;
relationName: string;
}): Promise<{ relationResults: any[]; relationAggregatedFieldsResult: any }> {
if (ids.length === 0) {
return { relationResults: [], relationAggregatedFieldsResult: {} };
}
const aggregateForRelation = aggregate[relationName];
let relationAggregatedFieldsResult: Record<string, any> = {};
if (aggregateForRelation) {
const aggregateQueryBuilder = referenceQueryBuilder.clone();
this.processAggregateHelper.addSelectedAggregatedFieldsQueriesToQueryBuilder(
{
selectedAggregatedFields: aggregateForRelation,
queryBuilder: aggregateQueryBuilder,
},
);
const aggregatedFieldsValues = await aggregateQueryBuilder
.addSelect(column)
.where(`${column} IN (:...ids)`, {
ids,
})
.groupBy(column)
.getRawMany();
relationAggregatedFieldsResult = aggregatedFieldsValues.reduce(
(acc, item) => {
const columnWithoutQuotes = column.replace(/["']/g, '');
const key = item[columnWithoutQuotes];
const { [column]: _, ...itemWithoutColumn } = item;
acc[key] = itemWithoutColumn;
return acc;
},
{},
);
}
const result = await referenceQueryBuilder
.where(`${column} IN (:...ids)`, {
ids,
})
.take(limit)
.getMany();
const relationResults = formatResult<ObjectRecord[]>(
result,
referenceObjectMetadata,
objectMetadataMaps,
false,
);
return { relationResults, relationAggregatedFieldsResult };
}
private assignFromRelationResults({
parentRecords,
parentObjectRecordsAggregatedValues,
relationResults,
relationAggregatedFieldsResult,
relationName,
joinField,
}: {
parentRecords: ObjectRecord[];
parentObjectRecordsAggregatedValues: Record<string, any>;
relationResults: any[];
relationAggregatedFieldsResult: Record<string, any>;
relationName: string;
joinField: string;
}): void {
parentRecords.forEach((item) => {
item[relationName] = relationResults.filter(
(rel) => rel[joinField] === item.id,
);
});
parentObjectRecordsAggregatedValues[relationName] =
relationAggregatedFieldsResult;
}
private assignToRelationResults({
parentRecords,
parentObjectRecordsAggregatedValues,
relationResults,
relationAggregatedFieldsResult,
relationName,
}: {
parentRecords: ObjectRecord[];
parentObjectRecordsAggregatedValues: Record<string, any>;
relationResults: any[];
relationAggregatedFieldsResult: Record<string, any>;
relationName: string;
}): void {
parentRecords.forEach((item) => {
if (relationResults.length === 0) {
item[`${relationName}Id`] = null;
}
item[relationName] =
relationResults.find((rel) => rel.id === item[`${relationName}Id`]) ??
null;
});
parentObjectRecordsAggregatedValues[relationName] =
relationAggregatedFieldsResult;
}
} }

View File

@ -138,7 +138,6 @@ export abstract class GraphqlQueryBaseResolverService<
objectMetadataItemWithFieldMaps.fieldsByName, objectMetadataItemWithFieldMaps.fieldsByName,
objectMetadataItemWithFieldMaps.fieldsByJoinColumnName, objectMetadataItemWithFieldMaps.fieldsByJoinColumnName,
options.objectMetadataMaps, options.objectMetadataMaps,
featureFlagsMap,
); );
const selectedFields = graphqlFields(options.info); const selectedFields = graphqlFields(options.info);
@ -170,7 +169,6 @@ export abstract class GraphqlQueryBaseResolverService<
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
authContext.workspace.id, authContext.workspace.id,
options.objectMetadataMaps, options.objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
const resultWithGettersArray = Array.isArray(resultWithGetters) const resultWithGettersArray = Array.isArray(resultWithGetters)

View File

@ -14,7 +14,6 @@ import { CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolve
import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant'; import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util'; import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util'; import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
@ -30,7 +29,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<CreateManyResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<CreateManyResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord[]> { ): Promise<ObjectRecord[]> {
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -44,7 +42,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
objectRecords, objectRecords,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap,
); );
this.apiEventEmitterService.emitCreateEvents( this.apiEventEmitterService.emitCreateEvents(
@ -60,7 +57,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
upsertedRecords, upsertedRecords,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap,
shouldBypassPermissionChecks, shouldBypassPermissionChecks,
roleId, roleId,
); );
@ -69,7 +65,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
upsertedRecords, upsertedRecords,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap,
); );
} }
@ -305,7 +300,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
objectRecords: InsertResult, objectRecords: InsertResult,
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord[]> { ): Promise<ObjectRecord[]> {
const queryBuilder = executionArgs.repository.createQueryBuilder( const queryBuilder = executionArgs.repository.createQueryBuilder(
objectMetadataItemWithFieldMaps.nameSingular, objectMetadataItemWithFieldMaps.nameSingular,
@ -322,7 +316,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
nonFormattedUpsertedRecords, nonFormattedUpsertedRecords,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
} }
@ -331,7 +324,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
upsertedRecords: ObjectRecord[], upsertedRecords: ObjectRecord[],
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
shouldBypassPermissionChecks: boolean, shouldBypassPermissionChecks: boolean,
roleId?: string, roleId?: string,
): Promise<void> { ): Promise<void> {
@ -347,8 +339,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext: executionArgs.options.authContext, authContext: executionArgs.options.authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks, shouldBypassPermissionChecks,
}); });
@ -358,13 +348,9 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
upsertedRecords: ObjectRecord[], upsertedRecords: ObjectRecord[],
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): ObjectRecord[] { ): ObjectRecord[] {
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return upsertedRecords.map((record: ObjectRecord) => return upsertedRecords.map((record: ObjectRecord) =>
typeORMObjectRecordsParser.processRecord({ typeORMObjectRecordsParser.processRecord({

View File

@ -13,7 +13,6 @@ import { CreateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver
import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant'; import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util'; import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util'; import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
@ -24,7 +23,6 @@ export class GraphqlQueryCreateOneResolverService extends GraphqlQueryBaseResolv
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<CreateOneResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<CreateOneResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord> { ): Promise<ObjectRecord> {
const { authContext, objectMetadataMaps, objectMetadataItemWithFieldMaps } = const { authContext, objectMetadataMaps, objectMetadataItemWithFieldMaps } =
executionArgs.options; executionArgs.options;
@ -53,7 +51,6 @@ export class GraphqlQueryCreateOneResolverService extends GraphqlQueryBaseResolv
nonFormattedUpsertedRecords, nonFormattedUpsertedRecords,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
this.apiEventEmitterService.emitCreateEvents( this.apiEventEmitterService.emitCreateEvents(
@ -71,18 +68,13 @@ export class GraphqlQueryCreateOneResolverService extends GraphqlQueryBaseResolv
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext, authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey, shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
}); });
} }
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return typeORMObjectRecordsParser.processRecord({ return typeORMObjectRecordsParser.processRecord({
objectRecord: upsertedRecords[0], objectRecord: upsertedRecords[0],

View File

@ -11,7 +11,6 @@ import { DeleteManyResolverArgs } from 'src/engine/api/graphql/workspace-resolve
import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant'; import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util'; import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util'; import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
import { computeTableName } from 'src/engine/utils/compute-table-name.util'; import { computeTableName } from 'src/engine/utils/compute-table-name.util';
@ -23,7 +22,6 @@ export class GraphqlQueryDeleteManyResolverService extends GraphqlQueryBaseResol
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<DeleteManyResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<DeleteManyResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord[]> { ): Promise<ObjectRecord[]> {
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -54,7 +52,6 @@ export class GraphqlQueryDeleteManyResolverService extends GraphqlQueryBaseResol
nonFormattedDeletedObjectRecords.raw, nonFormattedDeletedObjectRecords.raw,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
this.apiEventEmitterService.emitDeletedEvents( this.apiEventEmitterService.emitDeletedEvents(
@ -72,18 +69,13 @@ export class GraphqlQueryDeleteManyResolverService extends GraphqlQueryBaseResol
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext, authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey, shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
}); });
} }
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return formattedDeletedRecords.map((record: ObjectRecord) => return formattedDeletedRecords.map((record: ObjectRecord) =>
typeORMObjectRecordsParser.processRecord({ typeORMObjectRecordsParser.processRecord({

View File

@ -15,7 +15,6 @@ import {
} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util'; import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util'; import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
@ -26,7 +25,6 @@ export class GraphqlQueryDeleteOneResolverService extends GraphqlQueryBaseResolv
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<DeleteOneResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<DeleteOneResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord> { ): Promise<ObjectRecord> {
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -47,7 +45,6 @@ export class GraphqlQueryDeleteOneResolverService extends GraphqlQueryBaseResolv
nonFormattedDeletedObjectRecords.raw, nonFormattedDeletedObjectRecords.raw,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
this.apiEventEmitterService.emitDeletedEvents( this.apiEventEmitterService.emitDeletedEvents(
@ -74,18 +71,13 @@ export class GraphqlQueryDeleteOneResolverService extends GraphqlQueryBaseResolv
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext, authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey, shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
}); });
} }
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return typeORMObjectRecordsParser.processRecord({ return typeORMObjectRecordsParser.processRecord({
objectRecord: deletedRecord, objectRecord: deletedRecord,

View File

@ -10,7 +10,6 @@ import { DestroyManyResolverArgs } from 'src/engine/api/graphql/workspace-resolv
import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant'; import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
import { computeTableName } from 'src/engine/utils/compute-table-name.util'; import { computeTableName } from 'src/engine/utils/compute-table-name.util';
@ -21,7 +20,6 @@ export class GraphqlQueryDestroyManyResolverService extends GraphqlQueryBaseReso
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<DestroyManyResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<DestroyManyResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord[]> { ): Promise<ObjectRecord[]> {
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -52,7 +50,6 @@ export class GraphqlQueryDestroyManyResolverService extends GraphqlQueryBaseReso
nonFormattedDeletedObjectRecords.raw, nonFormattedDeletedObjectRecords.raw,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
this.apiEventEmitterService.emitDestroyEvents( this.apiEventEmitterService.emitDestroyEvents(
@ -70,18 +67,13 @@ export class GraphqlQueryDestroyManyResolverService extends GraphqlQueryBaseReso
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext, authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey, shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
}); });
} }
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return deletedRecords.map((record: ObjectRecord) => return deletedRecords.map((record: ObjectRecord) =>
typeORMObjectRecordsParser.processRecord({ typeORMObjectRecordsParser.processRecord({

View File

@ -14,7 +14,6 @@ import {
GraphqlQueryRunnerExceptionCode, GraphqlQueryRunnerExceptionCode,
} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
@Injectable() @Injectable()
@ -24,7 +23,6 @@ export class GraphqlQueryDestroyOneResolverService extends GraphqlQueryBaseResol
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<DestroyOneResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<DestroyOneResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord> { ): Promise<ObjectRecord> {
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -52,7 +50,6 @@ export class GraphqlQueryDestroyOneResolverService extends GraphqlQueryBaseResol
nonFormattedDeletedObjectRecords.raw, nonFormattedDeletedObjectRecords.raw,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
this.apiEventEmitterService.emitDestroyEvents( this.apiEventEmitterService.emitDestroyEvents(
@ -70,18 +67,13 @@ export class GraphqlQueryDestroyOneResolverService extends GraphqlQueryBaseResol
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext, authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey, shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
}); });
} }
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return typeORMObjectRecordsParser.processRecord({ return typeORMObjectRecordsParser.processRecord({
objectRecord: deletedRecords[0], objectRecord: deletedRecords[0],

View File

@ -23,7 +23,6 @@ import {
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser'; import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { settings } from 'src/engine/constants/settings'; import { settings } from 'src/engine/constants/settings';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { getObjectMetadataMapItemByNameSingular } from 'src/engine/metadata-modules/utils/get-object-metadata-map-item-by-name-singular.util'; import { getObjectMetadataMapItemByNameSingular } from 'src/engine/metadata-modules/utils/get-object-metadata-map-item-by-name-singular.util';
import { formatData } from 'src/engine/twenty-orm/utils/format-data.util'; import { formatData } from 'src/engine/twenty-orm/utils/format-data.util';
@ -39,7 +38,6 @@ export class GraphqlQueryFindDuplicatesResolverService extends GraphqlQueryBaseR
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<FindDuplicatesResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<FindDuplicatesResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<IConnection<ObjectRecord>[]> { ): Promise<IConnection<ObjectRecord>[]> {
const { objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -66,14 +64,10 @@ export class GraphqlQueryFindDuplicatesResolverService extends GraphqlQueryBaseR
objectMetadataItemWithFieldsMaps?.fieldsByName, objectMetadataItemWithFieldsMaps?.fieldsByName,
objectMetadataItemWithFieldsMaps?.fieldsByJoinColumnName, objectMetadataItemWithFieldsMaps?.fieldsByJoinColumnName,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap,
); );
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
let objectRecords: Partial<ObjectRecord>[] = []; let objectRecords: Partial<ObjectRecord>[] = [];
@ -86,7 +80,6 @@ export class GraphqlQueryFindDuplicatesResolverService extends GraphqlQueryBaseR
nonFormattedObjectRecords, nonFormattedObjectRecords,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
} else if (executionArgs.args.data && !isEmpty(executionArgs.args.data)) { } else if (executionArgs.args.data && !isEmpty(executionArgs.args.data)) {
objectRecords = formatData( objectRecords = formatData(
@ -133,7 +126,6 @@ export class GraphqlQueryFindDuplicatesResolverService extends GraphqlQueryBaseR
nonFormattedDuplicates, nonFormattedDuplicates,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
return typeORMObjectRecordsParser.createConnection({ return typeORMObjectRecordsParser.createConnection({

View File

@ -28,7 +28,6 @@ import {
getCursor, getCursor,
getPaginationInfo, getPaginationInfo,
} from 'src/engine/api/graphql/graphql-query-runner/utils/cursors.util'; } from 'src/engine/api/graphql/graphql-query-runner/utils/cursors.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
@Injectable() @Injectable()
@ -42,7 +41,6 @@ export class GraphqlQueryFindManyResolverService extends GraphqlQueryBaseResolve
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<FindManyResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<FindManyResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<IConnection<ObjectRecord>> { ): Promise<IConnection<ObjectRecord>> {
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -130,7 +128,6 @@ export class GraphqlQueryFindManyResolverService extends GraphqlQueryBaseResolve
nonFormattedObjectRecords, nonFormattedObjectRecords,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
const { hasNextPage, hasPreviousPage } = getPaginationInfo( const { hasNextPage, hasPreviousPage } = getPaginationInfo(
@ -157,18 +154,13 @@ export class GraphqlQueryFindManyResolverService extends GraphqlQueryBaseResolve
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext, authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey, shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
}); });
} }
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return typeORMObjectRecordsParser.createConnection({ return typeORMObjectRecordsParser.createConnection({
objectRecords, objectRecords,

View File

@ -21,7 +21,6 @@ import {
WorkspaceQueryRunnerException, WorkspaceQueryRunnerException,
WorkspaceQueryRunnerExceptionCode, WorkspaceQueryRunnerExceptionCode,
} from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception'; } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
@Injectable() @Injectable()
@ -31,7 +30,6 @@ export class GraphqlQueryFindOneResolverService extends GraphqlQueryBaseResolver
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<FindOneResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<FindOneResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord> { ): Promise<ObjectRecord> {
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -59,7 +57,6 @@ export class GraphqlQueryFindOneResolverService extends GraphqlQueryBaseResolver
nonFormattedObjectRecord, nonFormattedObjectRecord,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
if (!objectRecord) { if (!objectRecord) {
@ -80,18 +77,13 @@ export class GraphqlQueryFindOneResolverService extends GraphqlQueryBaseResolver
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext, authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey, shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
}); });
} }
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return typeORMObjectRecordsParser.processRecord({ return typeORMObjectRecordsParser.processRecord({
objectRecord: objectRecords[0], objectRecord: objectRecords[0],

View File

@ -11,7 +11,6 @@ import { RestoreManyResolverArgs } from 'src/engine/api/graphql/workspace-resolv
import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant'; import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util'; import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util'; import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
import { computeTableName } from 'src/engine/utils/compute-table-name.util'; import { computeTableName } from 'src/engine/utils/compute-table-name.util';
@ -23,7 +22,6 @@ export class GraphqlQueryRestoreManyResolverService extends GraphqlQueryBaseReso
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<RestoreManyResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<RestoreManyResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord[]> { ): Promise<ObjectRecord[]> {
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -54,7 +52,6 @@ export class GraphqlQueryRestoreManyResolverService extends GraphqlQueryBaseReso
nonFormattedRestoredObjectRecords.raw, nonFormattedRestoredObjectRecords.raw,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
this.apiEventEmitterService.emitRestoreEvents( this.apiEventEmitterService.emitRestoreEvents(
@ -72,18 +69,13 @@ export class GraphqlQueryRestoreManyResolverService extends GraphqlQueryBaseReso
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext, authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey, shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
}); });
} }
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return formattedRestoredRecords.map((record: ObjectRecord) => return formattedRestoredRecords.map((record: ObjectRecord) =>
typeORMObjectRecordsParser.processRecord({ typeORMObjectRecordsParser.processRecord({

View File

@ -15,7 +15,6 @@ import {
} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util'; import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util'; import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
@ -26,7 +25,6 @@ export class GraphqlQueryRestoreOneResolverService extends GraphqlQueryBaseResol
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<RestoreOneResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<RestoreOneResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord> { ): Promise<ObjectRecord> {
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -47,7 +45,6 @@ export class GraphqlQueryRestoreOneResolverService extends GraphqlQueryBaseResol
nonFormattedRestoredObjectRecords.raw, nonFormattedRestoredObjectRecords.raw,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
this.apiEventEmitterService.emitRestoreEvents( this.apiEventEmitterService.emitRestoreEvents(
@ -74,18 +71,13 @@ export class GraphqlQueryRestoreOneResolverService extends GraphqlQueryBaseResol
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext, authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey, shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
}); });
} }
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return typeORMObjectRecordsParser.processRecord({ return typeORMObjectRecordsParser.processRecord({
objectRecord: restoredRecord, objectRecord: restoredRecord,

View File

@ -17,7 +17,6 @@ import {
} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util'; import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util'; import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
import { formatData } from 'src/engine/twenty-orm/utils/format-data.util'; import { formatData } from 'src/engine/twenty-orm/utils/format-data.util';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
@ -30,7 +29,6 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<UpdateManyResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<UpdateManyResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord[]> { ): Promise<ObjectRecord[]> {
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -55,7 +53,6 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
existingRecords, existingRecords,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
if (isEmpty(formattedExistingRecords)) { if (isEmpty(formattedExistingRecords)) {
@ -90,7 +87,6 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
nonFormattedUpdatedObjectRecords.raw, nonFormattedUpdatedObjectRecords.raw,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
this.apiEventEmitterService.emitUpdateEvents( this.apiEventEmitterService.emitUpdateEvents(
@ -110,18 +106,13 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext, authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey, shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
}); });
} }
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return formattedUpdatedRecords.map((record: ObjectRecord) => return formattedUpdatedRecords.map((record: ObjectRecord) =>
typeORMObjectRecordsParser.processRecord({ typeORMObjectRecordsParser.processRecord({

View File

@ -17,7 +17,6 @@ import {
} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper'; import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util'; import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util'; import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
import { formatData } from 'src/engine/twenty-orm/utils/format-data.util'; import { formatData } from 'src/engine/twenty-orm/utils/format-data.util';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
@ -29,7 +28,6 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
> { > {
async resolve( async resolve(
executionArgs: GraphqlQueryResolverExecutionArgs<UpdateOneResolverArgs>, executionArgs: GraphqlQueryResolverExecutionArgs<UpdateOneResolverArgs>,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
): Promise<ObjectRecord> { ): Promise<ObjectRecord> {
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } = const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options; executionArgs.options;
@ -55,7 +53,6 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
existingRecords, existingRecords,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
if (isEmpty(formattedExistingRecords)) { if (isEmpty(formattedExistingRecords)) {
@ -75,7 +72,6 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
nonFormattedUpdatedObjectRecords.raw, nonFormattedUpdatedObjectRecords.raw,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
); );
this.apiEventEmitterService.emitUpdateEvents( this.apiEventEmitterService.emitUpdateEvents(
@ -104,18 +100,13 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
limit: QUERY_MAX_RECORDS, limit: QUERY_MAX_RECORDS,
authContext, authContext,
dataSource: executionArgs.dataSource, dataSource: executionArgs.dataSource,
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId, roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey, shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
}); });
} }
const typeORMObjectRecordsParser = const typeORMObjectRecordsParser =
new ObjectRecordsToGraphqlConnectionHelper( new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
objectMetadataMaps,
featureFlagsMap,
);
return typeORMObjectRecordsParser.processRecord({ return typeORMObjectRecordsParser.processRecord({
objectRecord: updatedRecord, objectRecord: updatedRecord,

View File

@ -1,48 +0,0 @@
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import {
deduceRelationDirection,
RelationDirection,
} from 'src/engine/utils/deduce-relation-direction.util';
export const getRelationObjectMetadata = (
fieldMetadata: FieldMetadataInterface,
objectMetadataMaps: ObjectMetadataMaps,
) => {
const relationMetadata = getRelationMetadata(fieldMetadata);
const relationDirection = deduceRelationDirection(
fieldMetadata,
relationMetadata,
);
const referencedObjectMetadata =
relationDirection === RelationDirection.TO
? objectMetadataMaps.byId[relationMetadata.fromObjectMetadataId]
: objectMetadataMaps.byId[relationMetadata.toObjectMetadataId];
if (!referencedObjectMetadata) {
throw new Error(
`Referenced object metadata not found for relation ${relationMetadata.id}`,
);
}
return referencedObjectMetadata;
};
export const getRelationMetadata = (
fieldMetadata: FieldMetadataInterface,
): RelationMetadataEntity => {
const relationMetadata =
fieldMetadata.fromRelationMetadata ?? fieldMetadata.toRelationMetadata;
if (!relationMetadata) {
throw new Error(
`Relation metadata not found for field ${fieldMetadata.name}`,
);
}
return relationMetadata;
};

View File

@ -71,7 +71,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId: string, objectMetadataItemId: string,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
workspaceId: string, workspaceId: string,
isNewRelationEnabled: boolean,
): Promise<IConnection<ObjectRecord>> { ): Promise<IConnection<ObjectRecord>> {
return { return {
...connection, ...connection,
@ -83,7 +82,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId, objectMetadataItemId,
objectMetadataMaps, objectMetadataMaps,
workspaceId, workspaceId,
isNewRelationEnabled,
), ),
})), })),
), ),
@ -95,7 +93,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId: string, objectMetadataItemId: string,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
workspaceId: string, workspaceId: string,
isNewRelationEnabled: boolean,
) { ) {
return { return {
...result, ...result,
@ -107,7 +104,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId, objectMetadataItemId,
objectMetadataMaps, objectMetadataMaps,
workspaceId, workspaceId,
isNewRelationEnabled,
), ),
), ),
), ),
@ -119,7 +115,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId: string, objectMetadataItemId: string,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
workspaceId: string, workspaceId: string,
isNewRelationEnabled: boolean,
) { ) {
return await Promise.all( return await Promise.all(
recordArray.map( recordArray.map(
@ -129,7 +124,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId, objectMetadataItemId,
objectMetadataMaps, objectMetadataMaps,
workspaceId, workspaceId,
isNewRelationEnabled,
), ),
), ),
); );
@ -140,7 +134,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId: string, objectMetadataItemId: string,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
workspaceId: string, workspaceId: string,
isNewRelationEnabled: boolean,
): Promise<ObjectRecord> { ): Promise<ObjectRecord> {
const objectMetadataMapItem = objectMetadataMaps.byId[objectMetadataItemId]; const objectMetadataMapItem = objectMetadataMaps.byId[objectMetadataItemId];
@ -165,55 +158,17 @@ export class QueryResultGettersFactory {
>; >;
for (const relationField of relationFields) { for (const relationField of relationFields) {
if (!isNewRelationEnabled) { if (!isDefined(relationField.relationTargetObjectMetadataId)) {
const relationMetadata = throw new Error('Relation target object metadata id is not defined');
relationField.fromRelationMetadata ??
relationField.toRelationMetadata;
if (!isDefined(relationMetadata)) {
throw new Error('Relation metadata is not defined');
}
// TODO: computing this by taking the opposite of the current object metadata id
// is really less than ideal. This should be computed based on the relation metadata
// But right now it is too complex with the current structure and / or lack of utils
// around the possible combinations with relation metadata from / to + MANY_TO_ONE / ONE_TO_MANY
const relationObjectMetadataItemId =
relationMetadata.fromObjectMetadataId === objectMetadataItemId
? relationMetadata.toObjectMetadataId
: relationMetadata.fromObjectMetadataId;
const relationObjectMetadataItem =
objectMetadataMaps.byId[relationObjectMetadataItemId];
if (!isDefined(relationObjectMetadataItem)) {
throw new Error(
`Object metadata not found for id ${relationObjectMetadataItemId}`,
);
}
relationFieldsProcessedMap[relationField.name] =
await this.processQueryResultField(
record[relationField.name],
relationObjectMetadataItem.id,
objectMetadataMaps,
workspaceId,
isNewRelationEnabled,
);
} else {
if (!isDefined(relationField.relationTargetObjectMetadataId)) {
throw new Error('Relation target object metadata id is not defined');
}
relationFieldsProcessedMap[relationField.name] =
await this.processQueryResultField(
record[relationField.name],
relationField.relationTargetObjectMetadataId,
objectMetadataMaps,
workspaceId,
isNewRelationEnabled,
);
} }
relationFieldsProcessedMap[relationField.name] =
await this.processQueryResultField(
record[relationField.name],
relationField.relationTargetObjectMetadataId,
objectMetadataMaps,
workspaceId,
);
} }
const objectRecordProcessedWithoutRelationFields = await handler.handle( const objectRecordProcessedWithoutRelationFields = await handler.handle(
@ -234,7 +189,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId: string, objectMetadataItemId: string,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
workspaceId: string, workspaceId: string,
isNewRelationEnabled: boolean,
) { ) {
if (isQueryResultFieldValueAConnection(queryResultField)) { if (isQueryResultFieldValueAConnection(queryResultField)) {
return await this.processConnection( return await this.processConnection(
@ -242,7 +196,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId, objectMetadataItemId,
objectMetadataMaps, objectMetadataMaps,
workspaceId, workspaceId,
isNewRelationEnabled,
); );
} else if (isQueryResultFieldValueANestedRecordArray(queryResultField)) { } else if (isQueryResultFieldValueANestedRecordArray(queryResultField)) {
return await this.processNestedRecordArray( return await this.processNestedRecordArray(
@ -250,7 +203,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId, objectMetadataItemId,
objectMetadataMaps, objectMetadataMaps,
workspaceId, workspaceId,
isNewRelationEnabled,
); );
} else if (isQueryResultFieldValueARecordArray(queryResultField)) { } else if (isQueryResultFieldValueARecordArray(queryResultField)) {
return await this.processRecordArray( return await this.processRecordArray(
@ -258,7 +210,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId, objectMetadataItemId,
objectMetadataMaps, objectMetadataMaps,
workspaceId, workspaceId,
isNewRelationEnabled,
); );
} else if (isQueryResultFieldValueARecord(queryResultField)) { } else if (isQueryResultFieldValueARecord(queryResultField)) {
return await this.processRecord( return await this.processRecord(
@ -266,7 +217,6 @@ export class QueryResultGettersFactory {
objectMetadataItemId, objectMetadataItemId,
objectMetadataMaps, objectMetadataMaps,
workspaceId, workspaceId,
isNewRelationEnabled,
); );
} else { } else {
this.logger.warn( this.logger.warn(
@ -283,14 +233,12 @@ export class QueryResultGettersFactory {
objectMetadataItem: ObjectMetadataInterface, objectMetadataItem: ObjectMetadataInterface,
workspaceId: string, workspaceId: string,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
isNewRelationEnabled: boolean,
): Promise<any> { ): Promise<any> {
return await this.processQueryResultField( return await this.processQueryResultField(
result, result,
objectMetadataItem.id, objectMetadataItem.id,
objectMetadataMaps, objectMetadataMaps,
workspaceId, workspaceId,
isNewRelationEnabled,
); );
} }

View File

@ -36,7 +36,6 @@ export class InputTypeDefinitionFactory {
objectMetadata: ObjectMetadataInterface, objectMetadata: ObjectMetadataInterface,
kind: InputTypeDefinitionKind, kind: InputTypeDefinitionKind,
options: WorkspaceBuildSchemaOptions, options: WorkspaceBuildSchemaOptions,
isNewRelationEnabled = false,
): InputTypeDefinition { ): InputTypeDefinition {
const inputType = new GraphQLInputObjectType({ const inputType = new GraphQLInputObjectType({
name: `${pascalCase(objectMetadata.nameSingular)}${kind.toString()}Input`, name: `${pascalCase(objectMetadata.nameSingular)}${kind.toString()}Input`,
@ -59,7 +58,6 @@ export class InputTypeDefinitionFactory {
kind, kind,
options, options,
this.inputTypeFactory, this.inputTypeFactory,
isNewRelationEnabled,
), ),
and: { and: {
type: andOrType, type: andOrType,
@ -83,7 +81,6 @@ export class InputTypeDefinitionFactory {
kind, kind,
options, options,
this.inputTypeFactory, this.inputTypeFactory,
isNewRelationEnabled,
); );
} }
}, },

View File

@ -30,7 +30,6 @@ export class ObjectTypeDefinitionFactory {
objectMetadata: ObjectMetadataInterface, objectMetadata: ObjectMetadataInterface,
kind: ObjectTypeDefinitionKind, kind: ObjectTypeDefinitionKind,
options: WorkspaceBuildSchemaOptions, options: WorkspaceBuildSchemaOptions,
isNewRelationEnabled = false,
): ObjectTypeDefinition { ): ObjectTypeDefinition {
return { return {
target: objectMetadata.id, target: objectMetadata.id,
@ -43,7 +42,6 @@ export class ObjectTypeDefinitionFactory {
kind, kind,
options, options,
this.outputTypeFactory, this.outputTypeFactory,
isNewRelationEnabled,
), ),
}), }),
}; };

View File

@ -1,7 +1,5 @@
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import chalk from 'chalk';
import { CompositeType } from 'src/engine/metadata-modules/field-metadata/interfaces/composite-type.interface'; import { CompositeType } from 'src/engine/metadata-modules/field-metadata/interfaces/composite-type.interface';
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
@ -10,13 +8,10 @@ import { CompositeInputTypeDefinitionFactory } from 'src/engine/api/graphql/work
import { CompositeObjectTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/composite-object-type-definition.factory'; import { CompositeObjectTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/composite-object-type-definition.factory';
import { EnumTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/enum-type-definition.factory'; import { EnumTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/enum-type-definition.factory';
import { ExtendObjectTypeDefinitionV2Factory } from 'src/engine/api/graphql/workspace-schema-builder/factories/extend-object-type-definition-v2.factory'; import { ExtendObjectTypeDefinitionV2Factory } from 'src/engine/api/graphql/workspace-schema-builder/factories/extend-object-type-definition-v2.factory';
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 { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
import { ConnectionTypeDefinitionFactory } from './factories/connection-type-definition.factory'; import { ConnectionTypeDefinitionFactory } from './factories/connection-type-definition.factory';
import { EdgeTypeDefinitionFactory } from './factories/edge-type-definition.factory'; import { EdgeTypeDefinitionFactory } from './factories/edge-type-definition.factory';
import { ExtendObjectTypeDefinitionFactory } from './factories/extend-object-type-definition.factory';
import { import {
InputTypeDefinitionFactory, InputTypeDefinitionFactory,
InputTypeDefinitionKind, InputTypeDefinitionKind,
@ -43,24 +38,17 @@ export class TypeDefinitionsGenerator {
private readonly compositeInputTypeDefinitionFactory: CompositeInputTypeDefinitionFactory, private readonly compositeInputTypeDefinitionFactory: CompositeInputTypeDefinitionFactory,
private readonly edgeTypeDefinitionFactory: EdgeTypeDefinitionFactory, private readonly edgeTypeDefinitionFactory: EdgeTypeDefinitionFactory,
private readonly connectionTypeDefinitionFactory: ConnectionTypeDefinitionFactory, private readonly connectionTypeDefinitionFactory: ConnectionTypeDefinitionFactory,
private readonly extendObjectTypeDefinitionFactory: ExtendObjectTypeDefinitionFactory,
private readonly extendObjectTypeDefinitionV2Factory: ExtendObjectTypeDefinitionV2Factory, private readonly extendObjectTypeDefinitionV2Factory: ExtendObjectTypeDefinitionV2Factory,
private readonly featureFlagService: FeatureFlagService,
) {} ) {}
async generate( async generate(
objectMetadataCollection: ObjectMetadataInterface[], objectMetadataCollection: ObjectMetadataInterface[],
options: WorkspaceBuildSchemaOptions, options: WorkspaceBuildSchemaOptions,
isNewRelationEnabled: boolean,
) { ) {
// Generate composite type objects first because they can be used in dynamic objects // Generate composite type objects first because they can be used in dynamic objects
await this.generateCompositeTypeDefs(options); await this.generateCompositeTypeDefs(options);
// Generate metadata objects // Generate metadata objects
await this.generateMetadataTypeDefs( await this.generateMetadataTypeDefs(objectMetadataCollection, options);
objectMetadataCollection,
options,
isNewRelationEnabled,
);
} }
/** /**
@ -160,7 +148,6 @@ export class TypeDefinitionsGenerator {
private async generateMetadataTypeDefs( private async generateMetadataTypeDefs(
dynamicObjectMetadataCollection: ObjectMetadataInterface[], dynamicObjectMetadataCollection: ObjectMetadataInterface[],
options: WorkspaceBuildSchemaOptions, options: WorkspaceBuildSchemaOptions,
isNewRelationEnabled: boolean,
) { ) {
this.logger.log( this.logger.log(
`Generating metadata objects: [${dynamicObjectMetadataCollection `Generating metadata objects: [${dynamicObjectMetadataCollection
@ -170,17 +157,9 @@ export class TypeDefinitionsGenerator {
// Generate dynamic objects // Generate dynamic objects
this.generateEnumTypeDefs(dynamicObjectMetadataCollection, options); this.generateEnumTypeDefs(dynamicObjectMetadataCollection, options);
this.generateObjectTypeDefs( this.generateObjectTypeDefs(dynamicObjectMetadataCollection, options);
dynamicObjectMetadataCollection,
options,
isNewRelationEnabled,
);
this.generatePaginationTypeDefs(dynamicObjectMetadataCollection, options); this.generatePaginationTypeDefs(dynamicObjectMetadataCollection, options);
this.generateInputTypeDefs( this.generateInputTypeDefs(dynamicObjectMetadataCollection, options);
dynamicObjectMetadataCollection,
options,
isNewRelationEnabled,
);
await this.generateExtendedObjectTypeDefs( await this.generateExtendedObjectTypeDefs(
dynamicObjectMetadataCollection, dynamicObjectMetadataCollection,
options, options,
@ -190,14 +169,12 @@ export class TypeDefinitionsGenerator {
private generateObjectTypeDefs( private generateObjectTypeDefs(
objectMetadataCollection: ObjectMetadataInterface[] | CompositeType[], objectMetadataCollection: ObjectMetadataInterface[] | CompositeType[],
options: WorkspaceBuildSchemaOptions, options: WorkspaceBuildSchemaOptions,
isNewRelationEnabled: boolean,
) { ) {
const objectTypeDefs = objectMetadataCollection.map((objectMetadata) => const objectTypeDefs = objectMetadataCollection.map((objectMetadata) =>
this.objectTypeDefinitionFactory.create( this.objectTypeDefinitionFactory.create(
objectMetadata, objectMetadata,
ObjectTypeDefinitionKind.Plain, ObjectTypeDefinitionKind.Plain,
options, options,
isNewRelationEnabled,
), ),
); );
@ -225,7 +202,6 @@ export class TypeDefinitionsGenerator {
private generateInputTypeDefs( private generateInputTypeDefs(
objectMetadataCollection: ObjectMetadataInterface[], objectMetadataCollection: ObjectMetadataInterface[],
options: WorkspaceBuildSchemaOptions, options: WorkspaceBuildSchemaOptions,
isNewRelationEnabled: boolean,
) { ) {
const inputTypeDefs = objectMetadataCollection const inputTypeDefs = objectMetadataCollection
.map((objectMetadata) => { .map((objectMetadata) => {
@ -243,28 +219,24 @@ export class TypeDefinitionsGenerator {
objectMetadata, objectMetadata,
InputTypeDefinitionKind.Create, InputTypeDefinitionKind.Create,
options, options,
isNewRelationEnabled,
), ),
// Input type for update // Input type for update
this.inputTypeDefinitionFactory.create( this.inputTypeDefinitionFactory.create(
optionalExtendedObjectMetadata, optionalExtendedObjectMetadata,
InputTypeDefinitionKind.Update, InputTypeDefinitionKind.Update,
options, options,
isNewRelationEnabled,
), ),
// Filter input type // Filter input type
this.inputTypeDefinitionFactory.create( this.inputTypeDefinitionFactory.create(
optionalExtendedObjectMetadata, optionalExtendedObjectMetadata,
InputTypeDefinitionKind.Filter, InputTypeDefinitionKind.Filter,
options, options,
isNewRelationEnabled,
), ),
// OrderBy input type // OrderBy input type
this.inputTypeDefinitionFactory.create( this.inputTypeDefinitionFactory.create(
optionalExtendedObjectMetadata, optionalExtendedObjectMetadata,
InputTypeDefinitionKind.OrderBy, InputTypeDefinitionKind.OrderBy,
options, options,
isNewRelationEnabled,
), ),
]; ];
}) })
@ -300,34 +272,14 @@ export class TypeDefinitionsGenerator {
throw new Error('Workspace ID not found'); throw new Error('Workspace ID not found');
} }
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled( const objectTypeDefs = objectMetadataCollectionWithCompositeFields.map(
FeatureFlagKey.IsNewRelationEnabled, (objectMetadata) =>
workspaceId, this.extendObjectTypeDefinitionV2Factory.create(
objectMetadata,
options,
),
); );
if (!isNewRelationEnabled) { this.typeDefinitionsStorage.addObjectTypes(objectTypeDefs);
const objectTypeDefs = objectMetadataCollectionWithCompositeFields.map(
(objectMetadata) =>
this.extendObjectTypeDefinitionFactory.create(
objectMetadata,
options,
),
);
this.typeDefinitionsStorage.addObjectTypes(objectTypeDefs);
} else {
this.logger.log(
chalk.green('Extend object type definition with new relation fields'),
);
const objectTypeDefsV2 = objectMetadataCollectionWithCompositeFields.map(
(objectMetadata) =>
this.extendObjectTypeDefinitionV2Factory.create(
objectMetadata,
options,
),
);
this.typeDefinitionsStorage.addObjectTypes(objectTypeDefsV2);
}
} }
} }

View File

@ -41,7 +41,6 @@ export const generateFields = <
kind: T, kind: T,
options: WorkspaceBuildSchemaOptions, options: WorkspaceBuildSchemaOptions,
typeFactory: TypeFactory<T>, typeFactory: TypeFactory<T>,
isNewRelationEnabled = false,
): T extends InputTypeDefinitionKind ): T extends InputTypeDefinitionKind
? GraphQLInputFieldConfigMap ? GraphQLInputFieldConfigMap
: GraphQLFieldConfigMap<any, any> => { : GraphQLFieldConfigMap<any, any> => {
@ -53,8 +52,7 @@ export const generateFields = <
fieldMetadata, fieldMetadata,
FieldMetadataType.RELATION, FieldMetadataType.RELATION,
) && ) &&
(fieldMetadata.settings?.relationType !== RelationType.MANY_TO_ONE || fieldMetadata.settings?.relationType !== RelationType.MANY_TO_ONE
!isNewRelationEnabled)
) { ) {
continue; continue;
} }

View File

@ -25,13 +25,11 @@ export class WorkspaceGraphQLSchemaFactory {
objectMetadataCollection: ObjectMetadataInterface[], objectMetadataCollection: ObjectMetadataInterface[],
workspaceResolverBuilderMethods: WorkspaceResolverBuilderMethods, workspaceResolverBuilderMethods: WorkspaceResolverBuilderMethods,
options: WorkspaceBuildSchemaOptions = {}, options: WorkspaceBuildSchemaOptions = {},
isNewRelationEnabled = false,
): Promise<GraphQLSchema> { ): Promise<GraphQLSchema> {
// Generate type definitions // Generate type definitions
await this.typeDefinitionsGenerator.generate( await this.typeDefinitionsGenerator.generate(
objectMetadataCollection, objectMetadataCollection,
options, options,
isNewRelationEnabled,
); );
// Generate schema // Generate schema

View File

@ -1,7 +1,6 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { WorkspaceResolverBuilderModule } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module'; import { WorkspaceResolverBuilderModule } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
import { TypeDefinitionsGenerator } from './type-definitions.generator'; import { TypeDefinitionsGenerator } from './type-definitions.generator';
@ -12,11 +11,7 @@ import { TypeMapperService } from './services/type-mapper.service';
import { TypeDefinitionsStorage } from './storages/type-definitions.storage'; import { TypeDefinitionsStorage } from './storages/type-definitions.storage';
@Module({ @Module({
imports: [ imports: [ObjectMetadataModule, WorkspaceResolverBuilderModule],
ObjectMetadataModule,
FeatureFlagModule,
WorkspaceResolverBuilderModule,
],
providers: [ providers: [
TypeDefinitionsStorage, TypeDefinitionsStorage,
TypeMapperService, TypeMapperService,

View File

@ -1,13 +1,10 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { makeExecutableSchema } from '@graphql-tools/schema'; import { makeExecutableSchema } from '@graphql-tools/schema';
import chalk from 'chalk';
import { GraphQLSchema, printSchema } from 'graphql'; import { GraphQLSchema, printSchema } from 'graphql';
import { gql } from 'graphql-tag'; import { gql } from 'graphql-tag';
import { isDefined } from 'twenty-shared/utils'; import { isDefined } from 'twenty-shared/utils';
import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface';
import { import {
GraphqlQueryRunnerException, GraphqlQueryRunnerException,
GraphqlQueryRunnerExceptionCode, GraphqlQueryRunnerExceptionCode,
@ -17,13 +14,12 @@ import { workspaceResolverBuilderMethodNames } from 'src/engine/api/graphql/work
import { WorkspaceResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory'; import { WorkspaceResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory';
import { WorkspaceGraphQLSchemaFactory } from 'src/engine/api/graphql/workspace-schema-builder/workspace-graphql-schema.factory'; import { WorkspaceGraphQLSchemaFactory } from 'src/engine/api/graphql/workspace-schema-builder/workspace-graphql-schema.factory';
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; 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 { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service'; import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service';
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
@Injectable() @Injectable()
export class WorkspaceSchemaFactory { export class WorkspaceSchemaFactory {
@ -43,21 +39,6 @@ export class WorkspaceSchemaFactory {
return new GraphQLSchema({}); return new GraphQLSchema({});
} }
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
authContext.workspace.id,
);
if (
isNewRelationEnabled &&
this.twentyConfigService.get('NODE_ENV') !== NodeEnvironment.test
) {
// eslint-disable-next-line no-console
console.log(
chalk.yellow('🚧 New relation schema generation is enabled 🚧'),
);
}
const dataSourcesMetadata = const dataSourcesMetadata =
await this.dataSourceService.getDataSourcesMetadataFromWorkspaceId( await this.dataSourceService.getDataSourcesMetadataFromWorkspaceId(
authContext.workspace.id, authContext.workspace.id,
@ -140,7 +121,6 @@ export class WorkspaceSchemaFactory {
objectMetadataCollection, objectMetadataCollection,
workspaceResolverBuilderMethodNames, workspaceResolverBuilderMethodNames,
{}, {},
isNewRelationEnabled,
); );
usedScalarNames = usedScalarNames =

View File

@ -11,7 +11,6 @@ export class RestApiGetManyHandler extends RestApiBaseHandler {
objectMetadataNameSingular, objectMetadataNameSingular,
objectMetadataNamePlural, objectMetadataNamePlural,
repository, repository,
dataSource,
objectMetadata, objectMetadata,
objectMetadataItemWithFieldsMaps, objectMetadataItemWithFieldsMaps,
} = await this.getRepositoryAndMetadataOrFail(request); } = await this.getRepositoryAndMetadataOrFail(request);
@ -20,7 +19,6 @@ export class RestApiGetManyHandler extends RestApiBaseHandler {
await this.findRecords({ await this.findRecords({
request, request,
repository, repository,
dataSource,
objectMetadata, objectMetadata,
objectMetadataNameSingular, objectMetadataNameSingular,
objectMetadataItemWithFieldsMaps, objectMetadataItemWithFieldsMaps,

View File

@ -21,7 +21,6 @@ export class RestApiGetOneHandler extends RestApiBaseHandler {
const { const {
objectMetadataNameSingular, objectMetadataNameSingular,
repository, repository,
dataSource,
objectMetadata, objectMetadata,
objectMetadataItemWithFieldsMaps, objectMetadataItemWithFieldsMaps,
} = await this.getRepositoryAndMetadataOrFail(request); } = await this.getRepositoryAndMetadataOrFail(request);
@ -30,7 +29,6 @@ export class RestApiGetOneHandler extends RestApiBaseHandler {
request, request,
recordId, recordId,
repository, repository,
dataSource,
objectMetadata, objectMetadata,
objectMetadataNameSingular, objectMetadataNameSingular,
objectMetadataItemWithFieldsMaps, objectMetadataItemWithFieldsMaps,

View File

@ -1,37 +1,35 @@
import { BadRequestException, Inject } from '@nestjs/common'; import { BadRequestException, Inject } from '@nestjs/common';
import { Request } from 'express'; import { Request } from 'express';
import { FieldMetadataType } from 'twenty-shared/types';
import { capitalize, isDefined } from 'twenty-shared/utils'; import { capitalize, isDefined } from 'twenty-shared/utils';
import { In, ObjectLiteral, SelectQueryBuilder } from 'typeorm'; import { In, ObjectLiteral, SelectQueryBuilder } from 'typeorm';
import { FieldMetadataType } from 'twenty-shared/types';
import { import {
ObjectRecord, ObjectRecord,
OrderByDirection, OrderByDirection,
} from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface'; } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
import { ApiEventEmitterService } from 'src/engine/api/graphql/graphql-query-runner/services/api-event-emitter.service';
import { CoreQueryBuilderFactory } from 'src/engine/api/rest/core/query-builder/core-query-builder.factory'; import { CoreQueryBuilderFactory } from 'src/engine/api/rest/core/query-builder/core-query-builder.factory';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { GetVariablesFactory } from 'src/engine/api/rest/core/query-builder/factories/get-variables.factory'; import { GetVariablesFactory } from 'src/engine/api/rest/core/query-builder/factories/get-variables.factory';
import { parseCorePath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-path.utils';
import { QueryVariables } from 'src/engine/api/rest/core/types/query-variables.type';
import { import {
Depth, Depth,
DepthInputFactory, DepthInputFactory,
MAX_DEPTH, MAX_DEPTH,
} from 'src/engine/api/rest/input-factories/depth-input.factory'; } from 'src/engine/api/rest/input-factories/depth-input.factory';
import { ApiEventEmitterService } from 'src/engine/api/graphql/graphql-query-runner/services/api-event-emitter.service';
import { WorkspacePermissionsCacheService } from 'src/engine/metadata-modules/workspace-permissions-cache/workspace-permissions-cache.service';
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { parseCorePath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-path.utils';
import { getObjectMetadataMapItemByNameSingular } from 'src/engine/metadata-modules/utils/get-object-metadata-map-item-by-name-singular.util';
import { RecordInputTransformerService } from 'src/engine/core-modules/record-transformer/services/record-input-transformer.service'; import { RecordInputTransformerService } from 'src/engine/core-modules/record-transformer/services/record-input-transformer.service';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser'; import { getObjectMetadataMapItemByNameSingular } from 'src/engine/metadata-modules/utils/get-object-metadata-map-item-by-name-singular.util';
import { WorkspacePermissionsCacheService } from 'src/engine/metadata-modules/workspace-permissions-cache/workspace-permissions-cache.service';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { formatResult as formatGetManyData } from 'src/engine/twenty-orm/utils/format-result.util'; import { formatResult as formatGetManyData } from 'src/engine/twenty-orm/utils/format-result.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { QueryVariables } from 'src/engine/api/rest/core/types/query-variables.type';
export interface PageInfo { export interface PageInfo {
hasNextPage?: boolean; hasNextPage?: boolean;
@ -284,7 +282,6 @@ export abstract class RestApiBaseHandler {
request, request,
recordId, recordId,
repository, repository,
dataSource,
objectMetadata, objectMetadata,
objectMetadataNameSingular, objectMetadataNameSingular,
objectMetadataItemWithFieldsMaps, objectMetadataItemWithFieldsMaps,
@ -292,7 +289,6 @@ export abstract class RestApiBaseHandler {
request: Request; request: Request;
recordId?: string; recordId?: string;
repository: WorkspaceRepository<ObjectLiteral>; repository: WorkspaceRepository<ObjectLiteral>;
dataSource: WorkspaceDataSource;
objectMetadata: any; objectMetadata: any;
objectMetadataNameSingular: string; objectMetadataNameSingular: string;
objectMetadataItemWithFieldsMaps: objectMetadataItemWithFieldsMaps:
@ -316,7 +312,6 @@ export abstract class RestApiBaseHandler {
fieldMetadataMapByName, fieldMetadataMapByName,
fieldMetadataMapByJoinColumnName, fieldMetadataMapByJoinColumnName,
objectMetadata.objectMetadataMaps, objectMetadata.objectMetadataMaps,
dataSource.featureFlagMap,
); );
const filters = this.computeFilters(inputs); const filters = this.computeFilters(inputs);
@ -366,7 +361,6 @@ export abstract class RestApiBaseHandler {
records, records,
objectMetadataItemWithFieldsMaps as any, objectMetadataItemWithFieldsMaps as any,
objectMetadata.objectMetadataMaps, objectMetadata.objectMetadataMaps,
dataSource.featureFlagMap[FeatureFlagKey.IsNewRelationEnabled],
), ),
totalCount, totalCount,
hasMoreRecords, hasMoreRecords,

View File

@ -7,6 +7,5 @@ export enum FeatureFlagKey {
IsUniqueIndexesEnabled = 'IS_UNIQUE_INDEXES_ENABLED', IsUniqueIndexesEnabled = 'IS_UNIQUE_INDEXES_ENABLED',
IsJsonFilterEnabled = 'IS_JSON_FILTER_ENABLED', IsJsonFilterEnabled = 'IS_JSON_FILTER_ENABLED',
IsCustomDomainEnabled = 'IS_CUSTOM_DOMAIN_ENABLED', IsCustomDomainEnabled = 'IS_CUSTOM_DOMAIN_ENABLED',
IsNewRelationEnabled = 'IS_NEW_RELATION_ENABLED',
IsPermissionsV2Enabled = 'IS_PERMISSIONS_V2_ENABLED', IsPermissionsV2Enabled = 'IS_PERMISSIONS_V2_ENABLED',
} }

View File

@ -1,13 +1,12 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { FileModule } from 'src/engine/core-modules/file/file.module'; import { FileModule } from 'src/engine/core-modules/file/file.module';
import { SearchResolver } from 'src/engine/core-modules/search/search.resolver'; import { SearchResolver } from 'src/engine/core-modules/search/search.resolver';
import { SearchService } from 'src/engine/core-modules/search/services/search.service'; import { SearchService } from 'src/engine/core-modules/search/services/search.service';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module'; import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
@Module({ @Module({
imports: [WorkspaceCacheStorageModule, FeatureFlagModule, FileModule], imports: [WorkspaceCacheStorageModule, FileModule],
providers: [SearchResolver, SearchService], providers: [SearchResolver, SearchService],
}) })
export class SearchModule {} export class SearchModule {}

View File

@ -5,7 +5,6 @@ import chunk from 'lodash.chunk';
import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface'; import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { SearchArgs } from 'src/engine/core-modules/search/dtos/search-args'; import { SearchArgs } from 'src/engine/core-modules/search/dtos/search-args';
import { SearchRecordDTO } from 'src/engine/core-modules/search/dtos/search-record-dto'; import { SearchRecordDTO } from 'src/engine/core-modules/search/dtos/search-record-dto';
import { import {
@ -30,7 +29,6 @@ export class SearchResolver {
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
private readonly twentyORMManager: TwentyORMManager, private readonly twentyORMManager: TwentyORMManager,
private readonly searchService: SearchService, private readonly searchService: SearchService,
private readonly featureFlagService: FeatureFlagService,
) {} ) {}
@Query(() => [SearchRecordDTO]) @Query(() => [SearchRecordDTO])
@ -68,9 +66,6 @@ export class SearchResolver {
); );
} }
const featureFlagMap =
await this.featureFlagService.getWorkspaceFeatureFlagsMap(workspace.id);
const objectMetadataItemWithFieldMaps = Object.values( const objectMetadataItemWithFieldMaps = Object.values(
objectMetadataMaps.byId, objectMetadataMaps.byId,
); );
@ -102,7 +97,6 @@ export class SearchResolver {
records: await this.searchService.buildSearchQueryAndGetRecords({ records: await this.searchService.buildSearchQueryAndGetRecords({
entityManager: repository, entityManager: repository,
objectMetadataItem, objectMetadataItem,
featureFlagMap,
searchTerms: formatSearchTerms(searchInput, 'and'), searchTerms: formatSearchTerms(searchInput, 'and'),
searchTermsOr: formatSearchTerms(searchInput, 'or'), searchTermsOr: formatSearchTerms(searchInput, 'or'),
limit, limit,

View File

@ -6,7 +6,6 @@ import { getLogoUrlFromDomainName } from 'twenty-shared/utils';
import { Brackets, ObjectLiteral } from 'typeorm'; import { Brackets, ObjectLiteral } from 'typeorm';
import { ObjectRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface'; import { ObjectRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser'; import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
import { FileService } from 'src/engine/core-modules/file/services/file.service'; import { FileService } from 'src/engine/core-modules/file/services/file.service';
@ -57,7 +56,6 @@ export class SearchService {
async buildSearchQueryAndGetRecords<Entity extends ObjectLiteral>({ async buildSearchQueryAndGetRecords<Entity extends ObjectLiteral>({
entityManager, entityManager,
objectMetadataItem, objectMetadataItem,
featureFlagMap,
searchTerms, searchTerms,
searchTermsOr, searchTermsOr,
limit, limit,
@ -65,7 +63,6 @@ export class SearchService {
}: { }: {
entityManager: WorkspaceRepository<Entity>; entityManager: WorkspaceRepository<Entity>;
objectMetadataItem: ObjectMetadataItemWithFieldMaps; objectMetadataItem: ObjectMetadataItemWithFieldMaps;
featureFlagMap: FeatureFlagMap;
searchTerms: string; searchTerms: string;
searchTermsOr: string; searchTermsOr: string;
limit: number; limit: number;
@ -77,7 +74,6 @@ export class SearchService {
objectMetadataItem.fieldsByName, objectMetadataItem.fieldsByName,
objectMetadataItem.fieldsByJoinColumnName, objectMetadataItem.fieldsByJoinColumnName,
generateObjectMetadataMaps([objectMetadataItem]), generateObjectMetadataMaps([objectMetadataItem]),
featureFlagMap,
); );
queryParser.applyFilterToBuilder( queryParser.applyFilterToBuilder(

View File

@ -9,7 +9,6 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
import { ActorModule } from 'src/engine/core-modules/actor/actor.module'; import { ActorModule } from 'src/engine/core-modules/actor/actor.module';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto'; import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
@ -49,7 +48,6 @@ import { UpdateFieldInput } from './dtos/update-field.input';
WorkspaceMigrationRunnerModule, WorkspaceMigrationRunnerModule,
WorkspaceMetadataVersionModule, WorkspaceMetadataVersionModule,
WorkspaceCacheStorageModule, WorkspaceCacheStorageModule,
FeatureFlagModule,
ObjectMetadataModule, ObjectMetadataModule,
DataSourceModule, DataSourceModule,
TypeORMModule, TypeORMModule,

View File

@ -10,8 +10,6 @@ import {
import { FieldMetadataType } from 'twenty-shared/types'; import { FieldMetadataType } from 'twenty-shared/types';
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 { import {
ForbiddenError, ForbiddenError,
ValidationError, ValidationError,
@ -53,7 +51,6 @@ import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-
export class FieldMetadataResolver { export class FieldMetadataResolver {
constructor( constructor(
private readonly fieldMetadataService: FieldMetadataService, private readonly fieldMetadataService: FieldMetadataService,
private readonly featureFlagService: FeatureFlagService,
private readonly beforeUpdateOneField: BeforeUpdateOneField<UpdateFieldInput>, private readonly beforeUpdateOneField: BeforeUpdateOneField<UpdateFieldInput>,
) {} ) {}
@ -178,51 +175,28 @@ export class FieldMetadataResolver {
return null; return null;
} }
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled( const relation = await this.relation(
FeatureFlagKey.IsNewRelationEnabled, workspace,
workspace.id, fieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>,
context,
); );
// TODO: Remove this once we drop old relations or update the front-end to use the new relation if (!relation) {
if (isNewRelationEnabled) { return null;
const relation = await this.relation(
workspace,
fieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>,
context,
);
if (!relation) {
return null;
}
return {
// Temporary fix as we don't have relationId in the new relation
relationId: createDeterministicUuid([
relation.sourceFieldMetadata.id,
relation.targetFieldMetadata.id,
]),
direction: relation.type as unknown as RelationDefinitionType,
sourceObjectMetadata: relation.sourceObjectMetadata,
targetObjectMetadata: relation.targetObjectMetadata,
sourceFieldMetadata: relation.sourceFieldMetadata,
targetFieldMetadata: relation.targetFieldMetadata,
};
} }
try { return {
const relationMetadataItem = // Temporary fix as we don't have relationId in the new relation
await context.loaders.relationMetadataLoader.load({ relationId: createDeterministicUuid([
fieldMetadata, relation.sourceFieldMetadata.id,
workspaceId: workspace.id, relation.targetFieldMetadata.id,
}); ]),
direction: relation.type as unknown as RelationDefinitionType,
return await this.fieldMetadataService.getRelationDefinitionFromRelationMetadata( sourceObjectMetadata: relation.sourceObjectMetadata,
fieldMetadata, targetObjectMetadata: relation.targetObjectMetadata,
relationMetadataItem, sourceFieldMetadata: relation.sourceFieldMetadata,
); targetFieldMetadata: relation.targetFieldMetadata,
} catch (error) { };
fieldMetadataGraphqlApiExceptionHandler(error);
}
} }
@ResolveField(() => RelationDTO, { nullable: true }) @ResolveField(() => RelationDTO, { nullable: true })
@ -236,18 +210,6 @@ export class FieldMetadataResolver {
} }
try { try {
const isNewRelationEnabled =
await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
workspace.id,
);
if (!isNewRelationEnabled) {
throw new FieldMetadataException(
'New relation feature is not enabled for this workspace',
FieldMetadataExceptionCode.FIELD_METADATA_RELATION_NOT_ENABLED,
);
}
const { const {
sourceObjectMetadata, sourceObjectMetadata,
targetObjectMetadata, targetObjectMetadata,

View File

@ -10,7 +10,6 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { SettingsPermissionsGuard } from 'src/engine/guards/settings-permissions.guard'; import { SettingsPermissionsGuard } from 'src/engine/guards/settings-permissions.guard';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
@ -22,7 +21,6 @@ import { ObjectMetadataResolver } from 'src/engine/metadata-modules/object-metad
import { ObjectMetadataFieldRelationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service'; import { ObjectMetadataFieldRelationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service';
import { ObjectMetadataMigrationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service'; import { ObjectMetadataMigrationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service';
import { ObjectMetadataRelatedRecordsService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-related-records.service'; import { ObjectMetadataRelatedRecordsService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-related-records.service';
import { ObjectMetadataRelationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-relation.service';
import { SettingPermissionType } from 'src/engine/metadata-modules/permissions/constants/setting-permission-type.constants'; import { SettingPermissionType } from 'src/engine/metadata-modules/permissions/constants/setting-permission-type.constants';
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module'; import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
import { PermissionsGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/permissions/utils/permissions-graphql-api-exception.filter'; import { PermissionsGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/permissions/utils/permissions-graphql-api-exception.filter';
@ -58,14 +56,12 @@ import { UpdateObjectPayload } from './dtos/update-object.input';
RemoteTableRelationsModule, RemoteTableRelationsModule,
SearchVectorModule, SearchVectorModule,
IndexMetadataModule, IndexMetadataModule,
FeatureFlagModule,
PermissionsModule, PermissionsModule,
WorkspacePermissionsCacheModule, WorkspacePermissionsCacheModule,
], ],
services: [ services: [
ObjectMetadataService, ObjectMetadataService,
ObjectMetadataMigrationService, ObjectMetadataMigrationService,
ObjectMetadataRelationService,
ObjectMetadataFieldRelationService, ObjectMetadataFieldRelationService,
ObjectMetadataRelatedRecordsService, ObjectMetadataRelatedRecordsService,
], ],

View File

@ -10,8 +10,6 @@ import { FindManyOptions, FindOneOptions, In, Not, Repository } from 'typeorm';
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map'; import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
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 { generateMessageId } from 'src/engine/core-modules/i18n/utils/generateMessageId'; import { generateMessageId } from 'src/engine/core-modules/i18n/utils/generateMessageId';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@ -29,7 +27,6 @@ import {
import { ObjectMetadataFieldRelationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service'; import { ObjectMetadataFieldRelationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service';
import { ObjectMetadataMigrationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service'; import { ObjectMetadataMigrationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service';
import { ObjectMetadataRelatedRecordsService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-related-records.service'; import { ObjectMetadataRelatedRecordsService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-related-records.service';
import { ObjectMetadataRelationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-relation.service';
import { buildDefaultFieldsForCustomObject } from 'src/engine/metadata-modules/object-metadata/utils/build-default-fields-for-custom-object.util'; import { buildDefaultFieldsForCustomObject } from 'src/engine/metadata-modules/object-metadata/utils/build-default-fields-for-custom-object.util';
import { import {
validateLowerCasedAndTrimmedStringsAreDifferentOrThrow, validateLowerCasedAndTrimmedStringsAreDifferentOrThrow,
@ -64,13 +61,11 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService, private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
private readonly searchVectorService: SearchVectorService, private readonly searchVectorService: SearchVectorService,
private readonly objectMetadataRelationService: ObjectMetadataRelationService,
private readonly objectMetadataFieldRelationService: ObjectMetadataFieldRelationService, private readonly objectMetadataFieldRelationService: ObjectMetadataFieldRelationService,
private readonly objectMetadataMigrationService: ObjectMetadataMigrationService, private readonly objectMetadataMigrationService: ObjectMetadataMigrationService,
private readonly objectMetadataRelatedRecordsService: ObjectMetadataRelatedRecordsService, private readonly objectMetadataRelatedRecordsService: ObjectMetadataRelatedRecordsService,
private readonly indexMetadataService: IndexMetadataService, private readonly indexMetadataService: IndexMetadataService,
private readonly workspacePermissionsCacheService: WorkspacePermissionsCacheService, private readonly workspacePermissionsCacheService: WorkspacePermissionsCacheService,
private readonly featureFlagService: FeatureFlagService,
) { ) {
super(objectMetadataRepository); super(objectMetadataRepository);
} }
@ -188,33 +183,12 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
createdObjectMetadata.fields, createdObjectMetadata.fields,
); );
const isNewRelationEnabled = const createdRelatedObjectMetadataCollection =
await this.featureFlagService.isFeatureEnabled( await this.objectMetadataFieldRelationService.createRelationsAndForeignKeysMetadata(
FeatureFlagKey.IsNewRelationEnabled,
objectMetadataInput.workspaceId, objectMetadataInput.workspaceId,
createdObjectMetadata,
); );
let createdRelatedObjectMetadataCollection: ObjectMetadataEntity[];
if (isNewRelationEnabled) {
createdRelatedObjectMetadataCollection =
await this.objectMetadataFieldRelationService.createRelationsAndForeignKeysMetadata(
objectMetadataInput.workspaceId,
createdObjectMetadata,
);
} else {
createdRelatedObjectMetadataCollection =
await this.objectMetadataRelationService.createRelationsAndForeignKeysMetadata(
objectMetadataInput.workspaceId,
createdObjectMetadata,
{
primaryKeyFieldMetadataSettings:
objectMetadataInput.primaryKeyFieldMetadataSettings,
primaryKeyColumnType: objectMetadataInput.primaryKeyColumnType,
},
);
}
await this.objectMetadataMigrationService.createRelationMigrations( await this.objectMetadataMigrationService.createRelationMigrations(
createdObjectMetadata, createdObjectMetadata,
createdRelatedObjectMetadataCollection, createdRelatedObjectMetadataCollection,
@ -316,27 +290,12 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
const updatedObject = await super.updateOne(inputId, inputPayload); const updatedObject = await super.updateOne(inputId, inputPayload);
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
workspaceId,
);
await this.handleObjectNameAndLabelUpdates( await this.handleObjectNameAndLabelUpdates(
existingObjectMetadata, existingObjectMetadata,
existingObjectMetadataCombinedWithUpdateInput, existingObjectMetadataCombinedWithUpdateInput,
inputPayload, inputPayload,
); );
if (inputPayload.isActive !== undefined) {
// For new relation system, the active status is stitched to the field metadata
if (!isNewRelationEnabled) {
await this.objectMetadataRelationService.updateObjectRelationshipsActivationStatus(
inputId,
inputPayload.isActive,
);
}
}
await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations( await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations(
workspaceId, workspaceId,
); );
@ -377,11 +336,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
input: DeleteOneObjectInput, input: DeleteOneObjectInput,
workspaceId: string, workspaceId: string,
): Promise<ObjectMetadataEntity> { ): Promise<ObjectMetadataEntity> {
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
workspaceId,
);
const objectMetadata = await this.objectMetadataRepository.findOne({ const objectMetadata = await this.objectMetadataRepository.findOne({
relations: [ relations: [
'fields', 'fields',
@ -419,7 +373,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
await this.objectMetadataMigrationService.deleteAllRelationsAndDropTable( await this.objectMetadataMigrationService.deleteAllRelationsAndDropTable(
objectMetadata, objectMetadata,
workspaceId, workspaceId,
isNewRelationEnabled,
); );
} }
@ -536,11 +489,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
objectMetadataForUpdate: ObjectMetadataEntity, objectMetadataForUpdate: ObjectMetadataEntity,
inputPayload: UpdateObjectPayload, inputPayload: UpdateObjectPayload,
) { ) {
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
objectMetadataForUpdate.workspaceId,
);
const newTargetTableName = computeObjectTargetTable( const newTargetTableName = computeObjectTargetTable(
objectMetadataForUpdate, objectMetadataForUpdate,
); );
@ -555,33 +503,18 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
objectMetadataForUpdate.workspaceId, objectMetadataForUpdate.workspaceId,
); );
if (isNewRelationEnabled) { const relationMetadataCollection =
const relationMetadataCollection = await this.objectMetadataFieldRelationService.updateRelationsAndForeignKeysMetadata(
await this.objectMetadataFieldRelationService.updateRelationsAndForeignKeysMetadata(
objectMetadataForUpdate.workspaceId,
objectMetadataForUpdate,
);
await this.objectMetadataMigrationService.updateRelationMigrations(
existingObjectMetadata,
objectMetadataForUpdate,
relationMetadataCollection,
objectMetadataForUpdate.workspaceId, objectMetadataForUpdate.workspaceId,
);
} else {
const relationsAndForeignKeysMetadata =
await this.objectMetadataRelationService.updateRelationsAndForeignKeysMetadata(
objectMetadataForUpdate.workspaceId,
objectMetadataForUpdate,
);
await this.objectMetadataMigrationService.createUpdateForeignKeysMigrations(
existingObjectMetadata,
objectMetadataForUpdate, objectMetadataForUpdate,
relationsAndForeignKeysMetadata,
objectMetadataForUpdate.workspaceId,
); );
}
await this.objectMetadataMigrationService.updateRelationMigrations(
existingObjectMetadata,
objectMetadataForUpdate,
relationMetadataCollection,
objectMetadataForUpdate.workspaceId,
);
await this.objectMetadataMigrationService.recomputeEnumNames( await this.objectMetadataMigrationService.recomputeEnumNames(
objectMetadataForUpdate, objectMetadataForUpdate,

View File

@ -7,7 +7,6 @@ import { In, Repository } from 'typeorm';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { buildMigrationsForCustomObjectRelations } from 'src/engine/metadata-modules/object-metadata/utils/build-migrations-for-custom-object-relations.util'; import { buildMigrationsForCustomObjectRelations } from 'src/engine/metadata-modules/object-metadata/utils/build-migrations-for-custom-object-relations.util';
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
@ -30,8 +29,6 @@ import { RELATION_MIGRATION_PRIORITY_PREFIX } from 'src/engine/workspace-manager
@Injectable() @Injectable()
export class ObjectMetadataMigrationService { export class ObjectMetadataMigrationService {
constructor( constructor(
@InjectRepository(ObjectMetadataEntity, 'metadata')
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(FieldMetadataEntity, 'metadata') @InjectRepository(FieldMetadataEntity, 'metadata')
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>, private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
@InjectRepository(RelationMetadataEntity, 'metadata') @InjectRepository(RelationMetadataEntity, 'metadata')
@ -222,7 +219,6 @@ export class ObjectMetadataMigrationService {
public async deleteAllRelationsAndDropTable( public async deleteAllRelationsAndDropTable(
objectMetadata: ObjectMetadataEntity, objectMetadata: ObjectMetadataEntity,
workspaceId: string, workspaceId: string,
isNewRelationEnabled: boolean,
) { ) {
const relationsMetadataToDelete: RelationToDelete[] = []; const relationsMetadataToDelete: RelationToDelete[] = [];
@ -275,88 +271,59 @@ export class ObjectMetadataMigrationService {
relationToDelete.fromFieldMetadataId, relationToDelete.fromFieldMetadataId,
relationToDelete.toFieldMetadataId, relationToDelete.toFieldMetadataId,
]); ]);
if (relationToDelete.direction === 'from' && !isNewRelationEnabled) {
await this.workspaceMigrationService.createCustomMigration(
generateMigrationName(
`delete-${RELATION_MIGRATION_PRIORITY_PREFIX}-${relationToDelete.fromObjectName}-${relationToDelete.toObjectName}`,
),
workspaceId,
[
{
name: computeTableName(
relationToDelete.toObjectName,
relationToDelete.toObjectMetadataIsCustom,
),
action: WorkspaceMigrationTableActionType.ALTER,
columns: [
{
action: WorkspaceMigrationColumnActionType.DROP,
columnName: computeColumnName(
relationToDelete.toFieldMetadataName,
{ isForeignKey: true },
),
} satisfies WorkspaceMigrationColumnDrop,
],
},
],
);
}
} }
if (isNewRelationEnabled) { const manyToOneRelationFieldsToDelete = objectMetadata.fields.filter(
const manyToOneRelationFieldsToDelete = objectMetadata.fields.filter( (field) =>
(field) => isFieldMetadataInterfaceOfType(field, FieldMetadataType.RELATION) &&
isFieldMetadataInterfaceOfType(field, FieldMetadataType.RELATION) && (field as FieldMetadataEntity<FieldMetadataType.RELATION>).settings
(field as FieldMetadataEntity<FieldMetadataType.RELATION>).settings ?.relationType === RelationType.MANY_TO_ONE,
?.relationType === RelationType.MANY_TO_ONE, ) as FieldMetadataEntity<FieldMetadataType.RELATION>[];
) as FieldMetadataEntity<FieldMetadataType.RELATION>[];
const oneToManyRelationFieldsToDelete = objectMetadata.fields.filter( const oneToManyRelationFieldsToDelete = objectMetadata.fields.filter(
(field) => (field) =>
isFieldMetadataInterfaceOfType(field, FieldMetadataType.RELATION) && isFieldMetadataInterfaceOfType(field, FieldMetadataType.RELATION) &&
(field as FieldMetadataEntity<FieldMetadataType.RELATION>).settings (field as FieldMetadataEntity<FieldMetadataType.RELATION>).settings
?.relationType === RelationType.ONE_TO_MANY, ?.relationType === RelationType.ONE_TO_MANY,
); );
const relationFieldsToDelete = [ const relationFieldsToDelete = [
...manyToOneRelationFieldsToDelete, ...manyToOneRelationFieldsToDelete,
...(oneToManyRelationFieldsToDelete.map( ...(oneToManyRelationFieldsToDelete.map(
(field) => field.relationTargetFieldMetadata, (field) => field.relationTargetFieldMetadata,
) as FieldMetadataEntity<FieldMetadataType.RELATION>[]), ) as FieldMetadataEntity<FieldMetadataType.RELATION>[]),
]; ];
for (const relationFieldToDelete of relationFieldsToDelete) { for (const relationFieldToDelete of relationFieldsToDelete) {
const joinColumnName = relationFieldToDelete.settings?.joinColumnName; const joinColumnName = relationFieldToDelete.settings?.joinColumnName;
if (!joinColumnName) { if (!joinColumnName) {
throw new Error( throw new Error(
`Join column name is not set for relation field ${relationFieldToDelete.name}`, `Join column name is not set for relation field ${relationFieldToDelete.name}`,
);
}
await this.workspaceMigrationService.createCustomMigration(
generateMigrationName(
`delete-${RELATION_MIGRATION_PRIORITY_PREFIX}-${relationFieldToDelete.name}`,
),
workspaceId,
[
{
name: computeTableName(
relationFieldToDelete.object.nameSingular,
relationFieldToDelete.object.isCustom,
),
action: WorkspaceMigrationTableActionType.ALTER,
columns: [
{
action: WorkspaceMigrationColumnActionType.DROP,
columnName: joinColumnName,
} satisfies WorkspaceMigrationColumnDrop,
],
},
],
); );
} }
await this.workspaceMigrationService.createCustomMigration(
generateMigrationName(
`delete-${RELATION_MIGRATION_PRIORITY_PREFIX}-${relationFieldToDelete.name}`,
),
workspaceId,
[
{
name: computeTableName(
relationFieldToDelete.object.nameSingular,
relationFieldToDelete.object.isCustom,
),
action: WorkspaceMigrationTableActionType.ALTER,
columns: [
{
action: WorkspaceMigrationColumnActionType.DROP,
columnName: joinColumnName,
} satisfies WorkspaceMigrationColumnDrop,
],
},
],
);
} }
// DROP TABLE // DROP TABLE

View File

@ -1,451 +0,0 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { In, Repository } from 'typeorm';
import { capitalize } from 'twenty-shared/utils';
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { buildDescriptionForRelationFieldMetadataOnFromField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-from-field.util';
import { buildDescriptionForRelationFieldMetadataOnToField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-to-field.util';
import { buildNameLabelAndDescriptionForForeignKeyFieldMetadata } from 'src/engine/metadata-modules/object-metadata/utils/build-name-label-and-description-for-foreign-key-field-metadata.util';
import {
RelationMetadataEntity,
RelationMetadataType,
RelationOnDeleteAction,
} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
import { mapUdtNameToFieldType } from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util';
import {
CUSTOM_OBJECT_STANDARD_FIELD_IDS,
STANDARD_OBJECT_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
import {
createForeignKeyDeterministicUuid,
createRelationDeterministicUuid,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
const DEFAULT_RELATIONS_OBJECTS_STANDARD_IDS = [
STANDARD_OBJECT_IDS.timelineActivity,
STANDARD_OBJECT_IDS.favorite,
STANDARD_OBJECT_IDS.attachment,
STANDARD_OBJECT_IDS.noteTarget,
STANDARD_OBJECT_IDS.taskTarget,
];
@Injectable()
export class ObjectMetadataRelationService {
constructor(
@InjectRepository(ObjectMetadataEntity, 'metadata')
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(FieldMetadataEntity, 'metadata')
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
@InjectRepository(RelationMetadataEntity, 'metadata')
private readonly relationMetadataRepository: Repository<RelationMetadataEntity>,
) {}
public async createRelationsAndForeignKeysMetadata(
workspaceId: string,
createdObjectMetadata: ObjectMetadataEntity,
{ primaryKeyFieldMetadataSettings, primaryKeyColumnType },
) {
const relatedObjectMetadataCollection = await Promise.all(
DEFAULT_RELATIONS_OBJECTS_STANDARD_IDS.map(
async (relationObjectMetadataStandardId) =>
this.createRelationAndForeignKeyMetadata(
workspaceId,
createdObjectMetadata,
mapUdtNameToFieldType(primaryKeyColumnType ?? 'uuid'),
primaryKeyFieldMetadataSettings,
relationObjectMetadataStandardId,
),
),
);
return relatedObjectMetadataCollection;
}
private async createRelationAndForeignKeyMetadata(
workspaceId: string,
createdObjectMetadata: ObjectMetadataEntity,
objectPrimaryKeyType: FieldMetadataType,
objectPrimaryKeyFieldSettings:
| FieldMetadataSettings<FieldMetadataType>
| undefined,
relationObjectMetadataStandardId: string,
) {
const relatedObjectMetadata =
await this.objectMetadataRepository.findOneByOrFail({
standardId: relationObjectMetadataStandardId,
workspaceId: workspaceId,
isCustom: false,
});
const relationFieldMetadataCollection =
await this.createRelationFieldMetadas(
workspaceId,
createdObjectMetadata,
relatedObjectMetadata,
objectPrimaryKeyType,
objectPrimaryKeyFieldSettings,
);
await this.createRelationMetadataFromFieldMetadatas(
workspaceId,
createdObjectMetadata,
relatedObjectMetadata,
relationFieldMetadataCollection,
);
return relatedObjectMetadata;
}
private async createRelationFieldMetadas(
workspaceId: string,
createdObjectMetadata: ObjectMetadataEntity,
relatedObjectMetadata: ObjectMetadataEntity,
objectPrimaryKeyType: FieldMetadataType,
objectPrimaryKeyFieldSettings:
| FieldMetadataSettings<FieldMetadataType>
| undefined,
) {
return this.fieldMetadataRepository.save([
this.buildFromFieldMetadata(
workspaceId,
createdObjectMetadata,
relatedObjectMetadata,
),
this.buildToFieldMetadata(
workspaceId,
createdObjectMetadata,
relatedObjectMetadata,
),
this.buildForeignKeyFieldMetadata(
workspaceId,
createdObjectMetadata,
relatedObjectMetadata,
objectPrimaryKeyType,
objectPrimaryKeyFieldSettings,
),
]);
}
public async updateRelationsAndForeignKeysMetadata(
workspaceId: string,
updatedObjectMetadata: ObjectMetadataEntity,
): Promise<
{
relatedObjectMetadata: ObjectMetadataEntity;
foreignKeyFieldMetadata: FieldMetadataEntity;
toFieldMetadata: FieldMetadataEntity;
fromFieldMetadata: FieldMetadataEntity;
}[]
> {
return await Promise.all(
DEFAULT_RELATIONS_OBJECTS_STANDARD_IDS.map(
async (relationObjectMetadataStandardId) =>
this.updateRelationAndForeignKeyMetadata(
workspaceId,
updatedObjectMetadata,
relationObjectMetadataStandardId,
),
),
);
}
private async updateRelationAndForeignKeyMetadata(
workspaceId: string,
updatedObjectMetadata: ObjectMetadataEntity,
relationObjectMetadataStandardId: string,
) {
const relatedObjectMetadata =
await this.objectMetadataRepository.findOneByOrFail({
standardId: relationObjectMetadataStandardId,
workspaceId: workspaceId,
isCustom: false,
});
const toFieldMetadataUpdateCriteria = {
standardId: createRelationDeterministicUuid({
objectId: updatedObjectMetadata.id,
standardId:
STANDARD_OBJECT_FIELD_IDS[relatedObjectMetadata.nameSingular].custom,
}),
objectMetadataId: relatedObjectMetadata.id,
workspaceId: workspaceId,
};
const toFieldMetadataUpdateData = this.buildToFieldMetadata(
workspaceId,
updatedObjectMetadata,
relatedObjectMetadata,
true,
);
const toFieldMetadataToUpdate =
await this.fieldMetadataRepository.findOneBy(
toFieldMetadataUpdateCriteria,
);
const toFieldMetadata = await this.fieldMetadataRepository.save({
...toFieldMetadataToUpdate,
...toFieldMetadataUpdateData,
});
const fromFieldMetadataUpdateCriteria = {
standardId:
CUSTOM_OBJECT_STANDARD_FIELD_IDS[relatedObjectMetadata.namePlural],
objectMetadataId: updatedObjectMetadata.id,
workspaceId: workspaceId,
};
const fromFieldMetadataUpdateData = this.buildFromFieldMetadata(
workspaceId,
updatedObjectMetadata,
relatedObjectMetadata,
true,
);
const fromFieldMetadataToUpdate =
await this.fieldMetadataRepository.findOneBy(
fromFieldMetadataUpdateCriteria,
);
const fromFieldMetadata = await this.fieldMetadataRepository.save({
...fromFieldMetadataToUpdate,
...fromFieldMetadataUpdateData,
});
const foreignKeyFieldMetadataUpdateCriteria = {
standardId: createForeignKeyDeterministicUuid({
objectId: updatedObjectMetadata.id,
standardId:
STANDARD_OBJECT_FIELD_IDS[relatedObjectMetadata.nameSingular].custom,
}),
objectMetadataId: relatedObjectMetadata.id,
workspaceId: workspaceId,
};
const foreignKeyFieldMetadataUpdateData = this.buildForeignKeyFieldMetadata(
workspaceId,
updatedObjectMetadata,
relatedObjectMetadata,
FieldMetadataType.UUID,
undefined,
true,
);
const foreignKeyFieldMetadataToUpdate =
await this.fieldMetadataRepository.findOneBy(
foreignKeyFieldMetadataUpdateCriteria,
);
const foreignKeyFieldMetadata = await this.fieldMetadataRepository.save({
...foreignKeyFieldMetadataToUpdate,
...foreignKeyFieldMetadataUpdateData,
});
return {
relatedObjectMetadata,
foreignKeyFieldMetadata,
toFieldMetadata,
fromFieldMetadata,
};
}
private buildFromFieldMetadata(
workspaceId: string,
objectMetadata: ObjectMetadataEntity,
relatedObjectMetadata: ObjectMetadataEntity,
isUpdate = false,
) {
const relationObjectMetadataNamePlural = relatedObjectMetadata.namePlural;
const { description } = buildDescriptionForRelationFieldMetadataOnFromField(
{
relationObjectMetadataNamePlural,
targetObjectLabelSingular: objectMetadata.labelSingular,
},
);
return {
description,
...(!isUpdate
? {
standardId:
CUSTOM_OBJECT_STANDARD_FIELD_IDS[
relationObjectMetadataNamePlural
],
objectMetadataId: objectMetadata.id,
workspaceId: workspaceId,
isCustom: false,
isActive: true,
isSystem: true,
type: FieldMetadataType.RELATION,
name: relatedObjectMetadata.namePlural,
label: capitalize(relationObjectMetadataNamePlural),
description,
icon:
STANDARD_OBJECT_ICONS[relatedObjectMetadata.nameSingular] ||
'IconBuildingSkyscraper',
isNullable: true,
}
: {}),
};
}
private buildToFieldMetadata(
workspaceId: string,
objectMetadata: ObjectMetadataEntity,
relatedObjectMetadata: ObjectMetadataEntity,
isUpdate = false,
) {
const customStandardFieldId =
STANDARD_OBJECT_FIELD_IDS[relatedObjectMetadata.nameSingular].custom;
if (!customStandardFieldId) {
throw new Error(
`Custom standard field ID not found for ${relatedObjectMetadata.nameSingular}`,
);
}
const { description } = buildDescriptionForRelationFieldMetadataOnToField({
relationObjectMetadataNamePlural: relatedObjectMetadata.namePlural,
targetObjectLabelSingular: objectMetadata.labelSingular,
});
return {
name: objectMetadata.nameSingular,
label: objectMetadata.labelSingular,
description,
...(!isUpdate
? {
standardId: createRelationDeterministicUuid({
objectId: objectMetadata.id,
standardId: customStandardFieldId,
}),
objectMetadataId: relatedObjectMetadata.id,
workspaceId: workspaceId,
isCustom: false,
isActive: true,
isSystem: true,
type: FieldMetadataType.RELATION,
name: objectMetadata.nameSingular,
label: objectMetadata.labelSingular,
description,
icon: 'IconBuildingSkyscraper',
isNullable: true,
}
: {}),
};
}
private buildForeignKeyFieldMetadata(
workspaceId: string,
objectMetadata: ObjectMetadataEntity,
relatedObjectMetadata: ObjectMetadataEntity,
objectPrimaryKeyType: FieldMetadataType,
objectPrimaryKeyFieldSettings:
| FieldMetadataSettings<FieldMetadataType>
| undefined,
isUpdate = false,
) {
const customStandardFieldId =
STANDARD_OBJECT_FIELD_IDS[relatedObjectMetadata.nameSingular].custom;
if (!customStandardFieldId) {
throw new Error(
`Custom standard field ID not found for ${relatedObjectMetadata.nameSingular}`,
);
}
const { name, label, description } =
buildNameLabelAndDescriptionForForeignKeyFieldMetadata({
targetObjectNameSingular: objectMetadata.nameSingular,
targetObjectLabelSingular: objectMetadata.labelSingular,
relatedObjectLabelSingular: relatedObjectMetadata.labelSingular,
});
return {
name,
label,
description,
...(!isUpdate
? {
standardId: createForeignKeyDeterministicUuid({
objectId: objectMetadata.id,
standardId: customStandardFieldId,
}),
objectMetadataId: relatedObjectMetadata.id,
workspaceId: workspaceId,
isCustom: false,
isActive: true,
type: objectPrimaryKeyType,
name,
label,
description,
icon: undefined,
isNullable: true,
isSystem: true,
defaultValue: undefined,
settings: { ...objectPrimaryKeyFieldSettings, isForeignKey: true },
}
: {}),
};
}
private async createRelationMetadataFromFieldMetadatas(
workspaceId: string,
createdObjectMetadata: ObjectMetadataEntity,
relatedObjectMetadata: ObjectMetadataEntity,
relationFieldMetadataCollection: FieldMetadataEntity[],
) {
const relationFieldMetadataMap = relationFieldMetadataCollection.reduce(
(acc, fieldMetadata: FieldMetadataEntity) => {
if (fieldMetadata.type === FieldMetadataType.RELATION) {
acc[fieldMetadata.objectMetadataId] = fieldMetadata;
}
return acc;
},
{},
);
await this.relationMetadataRepository.save([
{
workspaceId: workspaceId,
relationType: RelationMetadataType.ONE_TO_MANY,
fromObjectMetadataId: createdObjectMetadata.id,
toObjectMetadataId: relatedObjectMetadata.id,
fromFieldMetadataId:
relationFieldMetadataMap[createdObjectMetadata.id].id,
toFieldMetadataId:
relationFieldMetadataMap[relatedObjectMetadata.id].id,
onDeleteAction: RelationOnDeleteAction.CASCADE,
},
]);
}
async updateObjectRelationshipsActivationStatus(
objectMetadataId: string,
isActive: boolean,
) {
const affectedRelations = await this.relationMetadataRepository.find({
where: [
{ fromObjectMetadataId: objectMetadataId },
{ toObjectMetadataId: objectMetadataId },
],
});
const affectedFieldIds = affectedRelations.reduce(
(acc, { fromFieldMetadataId, toFieldMetadataId }) => {
acc.push(fromFieldMetadataId, toFieldMetadataId);
return acc;
},
[] as string[],
);
if (affectedFieldIds.length > 0) {
await this.fieldMetadataRepository.update(
{ id: In(affectedFieldIds) },
{ isActive: isActive },
);
}
}
}

View File

@ -12,8 +12,6 @@ import { FieldMetadataDefaultSettings } from 'src/engine/metadata-modules/field-
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
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 { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service'; import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service';
import { IndexMetadataService } from 'src/engine/metadata-modules/index-metadata/index-metadata.service'; import { IndexMetadataService } from 'src/engine/metadata-modules/index-metadata/index-metadata.service';
@ -60,7 +58,6 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
private readonly indexMetadataService: IndexMetadataService, private readonly indexMetadataService: IndexMetadataService,
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
private readonly featureFlagService: FeatureFlagService,
) { ) {
super(relationMetadataRepository); super(relationMetadataRepository);
} }
@ -72,11 +69,6 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
relationMetadataInput, relationMetadataInput,
); );
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
relationMetadataInput.workspaceId,
);
try { try {
validateMetadataNameOrThrow(relationMetadataInput.fromName); validateMetadataNameOrThrow(relationMetadataInput.fromName);
validateMetadataNameOrThrow(relationMetadataInput.toName); validateMetadataNameOrThrow(relationMetadataInput.toName);
@ -116,15 +108,6 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
isCustom, isCustom,
toId, toId,
), ),
// We don't want to create the join column field metadata for new relation
...(isNewRelationEnabled
? []
: [
this.createForeignKeyFieldMetadata(
relationMetadataInput,
columnName,
),
]),
].flat(), ].flat(),
); );
@ -190,30 +173,6 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
this.throwIfDeletedAtFieldMetadataNotFound(deletedAtFieldMetadata); this.throwIfDeletedAtFieldMetadataNotFound(deletedAtFieldMetadata);
if (!isNewRelationEnabled) {
const foreignKeyFieldMetadata = createdRelationFieldsMetadata.find(
(fieldMetadata) => fieldMetadata.type === FieldMetadataType.UUID,
);
if (!foreignKeyFieldMetadata) {
throw new RelationMetadataException(
`ForeignKey field metadata not found`,
RelationMetadataExceptionCode.RELATION_METADATA_NOT_FOUND,
);
}
await this.indexMetadataService.createIndexMetadata(
relationMetadataInput.workspaceId,
toObjectMetadata,
[
foreignKeyFieldMetadata,
deletedAtFieldMetadata as FieldMetadataEntity<FieldMetadataType>,
],
false,
false,
);
}
await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations( await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations(
relationMetadataInput.workspaceId, relationMetadataInput.workspaceId,
); );

View File

@ -26,10 +26,7 @@ type EntitySchemaColumnMap = {
@Injectable() @Injectable()
export class EntitySchemaColumnFactory { export class EntitySchemaColumnFactory {
create( create(fieldMetadataMapByName: FieldMetadataMap): EntitySchemaColumnMap {
fieldMetadataMapByName: FieldMetadataMap,
isNewRelationEnabled: boolean,
): EntitySchemaColumnMap {
let entitySchemaColumnMap: EntitySchemaColumnMap = {}; let entitySchemaColumnMap: EntitySchemaColumnMap = {};
const fieldMetadataCollection = Object.values(fieldMetadataMapByName); const fieldMetadataCollection = Object.values(fieldMetadataMapByName);
@ -43,57 +40,28 @@ export class EntitySchemaColumnFactory {
FieldMetadataType.RELATION, FieldMetadataType.RELATION,
) )
) { ) {
if (!isNewRelationEnabled) { const isManyToOneRelation =
const relationMetadata = fieldMetadata.settings?.relationType === RelationType.MANY_TO_ONE;
fieldMetadata.fromRelationMetadata ?? const joinColumnName = fieldMetadata.settings?.joinColumnName;
fieldMetadata.toRelationMetadata;
if (!relationMetadata) {
throw new Error(
`Relation metadata is missing for field ${fieldMetadata.name}`,
);
}
const joinColumnKey = fieldMetadata.name + 'Id';
const joinColumn = fieldMetadataCollection.find(
(field) => field.name === joinColumnKey,
)
? joinColumnKey
: null;
if (joinColumn) {
entitySchemaColumnMap[joinColumn] = {
name: joinColumn,
type: 'uuid',
nullable: fieldMetadata.isNullable,
};
}
continue;
} else {
const isManyToOneRelation =
fieldMetadata.settings?.relationType === RelationType.MANY_TO_ONE;
const joinColumnName = fieldMetadata.settings?.joinColumnName;
if (!isManyToOneRelation) {
continue;
}
if (!isDefined(joinColumnName)) {
throw new TwentyORMException(
`Field ${fieldMetadata.id} of type ${fieldMetadata.type} is a many to one relation but does not have a join column name`,
TwentyORMExceptionCode.MALFORMED_METADATA,
);
}
entitySchemaColumnMap[joinColumnName] = {
name: joinColumnName,
type: 'uuid',
nullable: fieldMetadata.isNullable,
};
if (!isManyToOneRelation) {
continue; continue;
} }
if (!isDefined(joinColumnName)) {
throw new TwentyORMException(
`Field ${fieldMetadata.id} of type ${fieldMetadata.type} is a many to one relation but does not have a join column name`,
TwentyORMExceptionCode.MALFORMED_METADATA,
);
}
entitySchemaColumnMap[joinColumnName] = {
name: joinColumnName,
type: 'uuid',
nullable: fieldMetadata.isNullable,
};
continue;
} }
if (isCompositeFieldMetadataType(fieldMetadata.type)) { if (isCompositeFieldMetadataType(fieldMetadata.type)) {

View File

@ -5,7 +5,6 @@ import { EntitySchemaRelationOptions } from 'typeorm';
import { FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map'; import { FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { determineRelationDetails } from 'src/engine/twenty-orm/utils/determine-relation-details.util';
import { determineSchemaRelationDetails } from 'src/engine/twenty-orm/utils/determine-schema-relation-details.util'; import { determineSchemaRelationDetails } from 'src/engine/twenty-orm/utils/determine-schema-relation-details.util';
import { isFieldMetadataInterfaceOfType } from 'src/engine/utils/is-field-metadata-of-type.util'; import { isFieldMetadataInterfaceOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
@ -20,7 +19,6 @@ export class EntitySchemaRelationFactory {
async create( async create(
fieldMetadataMapByName: FieldMetadataMap, fieldMetadataMapByName: FieldMetadataMap,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
isNewRelationEnabled: boolean,
): Promise<EntitySchemaRelationMap> { ): Promise<EntitySchemaRelationMap> {
const entitySchemaRelationMap: EntitySchemaRelationMap = {}; const entitySchemaRelationMap: EntitySchemaRelationMap = {};
@ -36,48 +34,23 @@ export class EntitySchemaRelationFactory {
continue; continue;
} }
if (!isNewRelationEnabled) { if (!fieldMetadata.settings) {
const relationMetadata = throw new Error(
fieldMetadata.fromRelationMetadata ?? `Field metadata settings are missing for field ${fieldMetadata.name}`,
fieldMetadata.toRelationMetadata;
if (!relationMetadata) {
throw new Error(
`Relation metadata is missing for field ${fieldMetadata.name}`,
);
}
const relationDetails = await determineRelationDetails(
fieldMetadata,
relationMetadata,
objectMetadataMaps,
); );
entitySchemaRelationMap[fieldMetadata.name] = {
type: relationDetails.relationType,
target: relationDetails.target,
inverseSide: relationDetails.inverseSide,
joinColumn: relationDetails.joinColumn,
} satisfies EntitySchemaRelationOptions;
} else {
if (!fieldMetadata.settings) {
throw new Error(
`Field metadata settings are missing for field ${fieldMetadata.name}`,
);
}
const schemaRelationDetails = await determineSchemaRelationDetails(
fieldMetadata,
objectMetadataMaps,
);
entitySchemaRelationMap[fieldMetadata.name] = {
type: schemaRelationDetails.relationType,
target: schemaRelationDetails.target,
inverseSide: schemaRelationDetails.inverseSide,
joinColumn: schemaRelationDetails.joinColumn,
} satisfies EntitySchemaRelationOptions;
} }
const schemaRelationDetails = await determineSchemaRelationDetails(
fieldMetadata,
objectMetadataMaps,
);
entitySchemaRelationMap[fieldMetadata.name] = {
type: schemaRelationDetails.relationType,
target: schemaRelationDetails.target,
inverseSide: schemaRelationDetails.inverseSide,
joinColumn: schemaRelationDetails.joinColumn,
} satisfies EntitySchemaRelationOptions;
} }
return entitySchemaRelationMap; return entitySchemaRelationMap;

View File

@ -2,7 +2,6 @@ import { Injectable } from '@nestjs/common';
import { EntitySchema } from 'typeorm'; import { EntitySchema } from 'typeorm';
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 { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
@ -25,20 +24,13 @@ export class EntitySchemaFactory {
objectMetadata: ObjectMetadataItemWithFieldMaps, objectMetadata: ObjectMetadataItemWithFieldMaps,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
): Promise<EntitySchema> { ): Promise<EntitySchema> {
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
workspaceId,
);
const columns = this.entitySchemaColumnFactory.create( const columns = this.entitySchemaColumnFactory.create(
objectMetadata.fieldsByName, objectMetadata.fieldsByName,
isNewRelationEnabled,
); );
const relations = await this.entitySchemaRelationFactory.create( const relations = await this.entitySchemaRelationFactory.create(
objectMetadata.fieldsByName, objectMetadata.fieldsByName,
objectMetadataMaps, objectMetadataMaps,
isNewRelationEnabled,
); );
const entitySchema = new EntitySchema({ const entitySchema = new EntitySchema({

View File

@ -729,14 +729,7 @@ export class WorkspaceRepository<
objectMetadata ??= await this.getObjectMetadataFromTarget(); objectMetadata ??= await this.getObjectMetadataFromTarget();
const objectMetadataMaps = this.internalContext.objectMetadataMaps; const objectMetadataMaps = this.internalContext.objectMetadataMaps;
const isNewRelationEnabled =
this.internalContext.featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled];
return formatResult( return formatResult(data, objectMetadata, objectMetadataMaps) as T;
data,
objectMetadata,
objectMetadataMaps,
isNewRelationEnabled,
) as T;
} }
} }

View File

@ -8,10 +8,8 @@ import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metada
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { computeRelationType } from 'src/engine/twenty-orm/utils/compute-relation-type.util';
import { getCompositeFieldMetadataCollection } from 'src/engine/twenty-orm/utils/get-composite-field-metadata-collection'; import { getCompositeFieldMetadataCollection } from 'src/engine/twenty-orm/utils/get-composite-field-metadata-collection';
import { isFieldMetadataInterfaceOfType } from 'src/engine/utils/is-field-metadata-of-type.util'; import { isFieldMetadataInterfaceOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
import { isDate } from 'src/utils/date/isDate'; import { isDate } from 'src/utils/date/isDate';
@ -21,7 +19,6 @@ export function formatResult<T>(
data: any, data: any,
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps,
objectMetadataMaps: ObjectMetadataMaps, objectMetadataMaps: ObjectMetadataMaps,
isNewRelationEnabled: boolean,
): T { ): T {
if (!data) { if (!data) {
return data; return data;
@ -29,12 +26,7 @@ export function formatResult<T>(
if (Array.isArray(data)) { if (Array.isArray(data)) {
return data.map((item) => return data.map((item) =>
formatResult( formatResult(item, objectMetadataItemWithFieldMaps, objectMetadataMaps),
item,
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
isNewRelationEnabled,
),
) as T; ) as T;
} }
@ -50,36 +42,6 @@ export function formatResult<T>(
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
); );
const relationMetadataMap: Map<
string,
{
relationMetadata: RelationMetadataEntity | undefined;
relationType: string;
}
> = isNewRelationEnabled
? new Map()
: new Map(
Object.values(objectMetadataItemWithFieldMaps.fieldsById)
.filter((fieldMetadata) =>
isFieldMetadataInterfaceOfType(
fieldMetadata,
FieldMetadataType.RELATION,
),
)
.map((fieldMetadata) => [
fieldMetadata.name,
{
relationMetadata:
fieldMetadata.fromRelationMetadata ??
fieldMetadata.toRelationMetadata,
relationType: computeRelationType(
fieldMetadata,
fieldMetadata.fromRelationMetadata ??
(fieldMetadata.toRelationMetadata as RelationMetadataEntity),
),
},
]),
);
const newData: object = {}; const newData: object = {};
const objectMetadaItemFieldsByName = const objectMetadaItemFieldsByName =
objectMetadataMaps.byId[objectMetadataItemWithFieldMaps.id]?.fieldsByName; objectMetadataMaps.byId[objectMetadataItemWithFieldMaps.id]?.fieldsByName;
@ -104,7 +66,6 @@ export function formatResult<T>(
value, value,
objectMetadataItemWithFieldMaps, objectMetadataItemWithFieldMaps,
objectMetadataMaps, objectMetadataMaps,
isNewRelationEnabled,
); );
} else if (objectMetadaItemFieldsByName[key]) { } else if (objectMetadaItemFieldsByName[key]) {
newData[key] = formatFieldMetadataValue( newData[key] = formatFieldMetadataValue(
@ -118,63 +79,27 @@ export function formatResult<T>(
continue; continue;
} }
if (!isNewRelationEnabled) { if (isRelation) {
const { relationMetadata, relationType } = if (!isDefined(fieldMetadata?.relationTargetObjectMetadataId)) {
relationMetadataMap.get(key) ?? {}; throw new Error(
`Relation target object metadata ID is missing for field "${key}"`,
if (relationMetadata) {
const toObjectMetadata =
objectMetadataMaps.byId[relationMetadata.toObjectMetadataId];
const fromObjectMetadata =
objectMetadataMaps.byId[relationMetadata.fromObjectMetadataId];
if (!toObjectMetadata) {
throw new Error(
`Object metadata for object metadataId "${relationMetadata.toObjectMetadataId}" is missing`,
);
}
if (!fromObjectMetadata) {
throw new Error(
`Object metadata for object metadataId "${relationMetadata.fromObjectMetadataId}" is missing`,
);
}
newData[key] = formatResult(
value,
relationType === 'one-to-many'
? toObjectMetadata
: fromObjectMetadata,
objectMetadataMaps,
isNewRelationEnabled,
);
continue;
}
} else {
if (isRelation) {
if (!isDefined(fieldMetadata?.relationTargetObjectMetadataId)) {
throw new Error(
`Relation target object metadata ID is missing for field "${key}"`,
);
}
const targetObjectMetadata =
objectMetadataMaps.byId[fieldMetadata.relationTargetObjectMetadataId];
if (!targetObjectMetadata) {
throw new Error(
`Object metadata for object metadataId "${fieldMetadata.relationTargetObjectMetadataId}" is missing`,
);
}
newData[key] = formatResult(
value,
targetObjectMetadata,
objectMetadataMaps,
isNewRelationEnabled,
); );
} }
const targetObjectMetadata =
objectMetadataMaps.byId[fieldMetadata.relationTargetObjectMetadataId];
if (!targetObjectMetadata) {
throw new Error(
`Object metadata for object metadataId "${fieldMetadata.relationTargetObjectMetadataId}" is missing`,
);
}
newData[key] = formatResult(
value,
targetObjectMetadata,
objectMetadataMaps,
);
} }
if (!compositePropertyArgs) { if (!compositePropertyArgs) {

View File

@ -10,7 +10,6 @@ import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/
import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator';
import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service';
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
export enum WorkspaceCacheKeys { export enum WorkspaceCacheKeys {
@ -172,22 +171,6 @@ export class WorkspaceCacheStorageService {
); );
} }
// TODO: remove this after the feature flag is droped
setIsNewRelationEnabled(workspaceId: string, isNewRelationEnabled: boolean) {
return this.cacheStorageService.set<boolean>(
`${WorkspaceCacheKeys.GraphQLFeatureFlag}:${workspaceId}:${FeatureFlagKey.IsNewRelationEnabled}`,
isNewRelationEnabled,
TTL_INFINITE,
);
}
// TODO: remove this after the feature flag is droped
getIsNewRelationEnabled(workspaceId: string): Promise<boolean | undefined> {
return this.cacheStorageService.get<boolean>(
`${WorkspaceCacheKeys.GraphQLFeatureFlag}:${workspaceId}:${FeatureFlagKey.IsNewRelationEnabled}`,
);
}
getFeatureFlagsMapVersionFromCache( getFeatureFlagsMapVersionFromCache(
workspaceId: string, workspaceId: string,
): Promise<string | undefined> { ): Promise<string | undefined> {
@ -321,10 +304,5 @@ export class WorkspaceCacheStorageService {
await this.cacheStorageService.del( await this.cacheStorageService.del(
`${WorkspaceCacheKeys.FeatureFlagMapOngoingCachingLock}:${workspaceId}`, `${WorkspaceCacheKeys.FeatureFlagMapOngoingCachingLock}:${workspaceId}`,
); );
// TODO: remove this after the feature flag is droped
await this.cacheStorageService.del(
`${FeatureFlagKey.IsNewRelationEnabled}:${workspaceId}`,
);
} }
} }

View File

@ -5,7 +5,6 @@ import { FieldMetadataType } from 'twenty-shared/types';
import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface'; import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
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 { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
@ -95,13 +94,6 @@ export class WorkspaceMigrationFieldFactory {
return []; return [];
} }
const workspaceId = fieldMetadataCollection[0]?.workspaceId;
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
workspaceId,
);
const fieldMetadataCollectionGroupByObjectMetadataId = const fieldMetadataCollectionGroupByObjectMetadataId =
fieldMetadataCollection.reduce( fieldMetadataCollection.reduce(
(result, currentFieldMetadata) => { (result, currentFieldMetadata) => {
@ -125,14 +117,6 @@ export class WorkspaceMigrationFieldFactory {
originalObjectMetadataMap[fieldMetadataCollection[0]?.objectMetadataId]; originalObjectMetadataMap[fieldMetadataCollection[0]?.objectMetadataId];
for (const fieldMetadata of fieldMetadataCollection) { for (const fieldMetadata of fieldMetadataCollection) {
// Relations are handled in workspace-migration-relation.factory.ts
if (
!isNewRelationEnabled &&
fieldMetadata.type === FieldMetadataType.RELATION
) {
continue;
}
columns.push( columns.push(
...this.workspaceMigrationFactory.createColumnActions( ...this.workspaceMigrationFactory.createColumnActions(
WorkspaceMigrationColumnActionType.CREATE, WorkspaceMigrationColumnActionType.CREATE,
@ -172,22 +156,7 @@ export class WorkspaceMigrationFieldFactory {
return []; return [];
} }
const workspaceId = fieldMetadataUpdateCollection[0]?.current.workspaceId;
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
workspaceId,
);
for (const fieldMetadataUpdate of fieldMetadataUpdateCollection) { for (const fieldMetadataUpdate of fieldMetadataUpdateCollection) {
// Skip relations, because they're just representation and not real columns
if (
!isNewRelationEnabled &&
fieldMetadataUpdate.altered.type === FieldMetadataType.RELATION
) {
continue;
}
const columnActions = this.workspaceMigrationFactory.createColumnActions( const columnActions = this.workspaceMigrationFactory.createColumnActions(
WorkspaceMigrationColumnActionType.ALTER, WorkspaceMigrationColumnActionType.ALTER,
fieldMetadataUpdate.current, fieldMetadataUpdate.current,

View File

@ -1,3 +1 @@
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; export const DEFAULT_FEATURE_FLAGS = [];
export const DEFAULT_FEATURE_FLAGS = [FeatureFlagKey.IsNewRelationEnabled];

View File

@ -13,11 +13,8 @@ import {
} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface'; } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface';
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface'; import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage';
import { getJoinColumn } from 'src/engine/twenty-orm/utils/get-join-column.util';
import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util'; import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util';
@Injectable() @Injectable()
@ -169,21 +166,7 @@ export class StandardFieldFactory {
workspaceRelationMetadataArgs: WorkspaceRelationMetadataArgs, workspaceRelationMetadataArgs: WorkspaceRelationMetadataArgs,
context: WorkspaceSyncContext, context: WorkspaceSyncContext,
): PartialFieldMetadata[] { ): PartialFieldMetadata[] {
const isNewRelationEnabled =
context.featureFlags[FeatureFlagKey.IsNewRelationEnabled];
const fieldMetadataCollection: PartialFieldMetadata[] = []; const fieldMetadataCollection: PartialFieldMetadata[] = [];
const foreignKeyStandardId = createDeterministicUuid(
workspaceRelationMetadataArgs.standardId,
);
const joinColumnMetadataArgsCollection =
metadataArgsStorage.filterJoinColumns(
workspaceRelationMetadataArgs.target,
);
const joinColumn = getJoinColumn(
joinColumnMetadataArgsCollection,
workspaceRelationMetadataArgs,
);
if ( if (
isGatedAndNotEnabled( isGatedAndNotEnabled(
@ -194,28 +177,6 @@ export class StandardFieldFactory {
return []; return [];
} }
// We don't want to create the join column field metadata for new relation
if (!isNewRelationEnabled && joinColumn) {
fieldMetadataCollection.push({
type: FieldMetadataType.UUID,
standardId: foreignKeyStandardId,
name: joinColumn,
label: `${workspaceRelationMetadataArgs.label} id (foreign key)`,
description: `${workspaceRelationMetadataArgs.description} id foreign key`,
icon: workspaceRelationMetadataArgs.icon,
defaultValue: null,
options: undefined,
settings: undefined,
workspaceId: context.workspaceId,
isCustom: false,
isSystem: true,
isNullable: workspaceRelationMetadataArgs.isNullable,
isUnique:
workspaceRelationMetadataArgs.type === RelationType.ONE_TO_ONE,
isActive: workspaceRelationMetadataArgs.isActive ?? true,
});
}
fieldMetadataCollection.push({ fieldMetadataCollection.push({
type: FieldMetadataType.RELATION, type: FieldMetadataType.RELATION,
standardId: workspaceRelationMetadataArgs.standardId, standardId: workspaceRelationMetadataArgs.standardId,

View File

@ -17,7 +17,6 @@ import { PartialFieldMetadata } from 'src/engine/workspace-manager/workspace-syn
import { PartialIndexMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-index-metadata.interface'; import { PartialIndexMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-index-metadata.interface';
import { UpdaterOptions } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/updater-options.interface'; import { UpdaterOptions } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/updater-options.interface';
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 { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
import { FieldMetadataComplexOption } from 'src/engine/metadata-modules/field-metadata/dtos/options.input'; import { FieldMetadataComplexOption } from 'src/engine/metadata-modules/field-metadata/dtos/options.input';
@ -369,15 +368,6 @@ export class WorkspaceMetadataUpdaterService {
createdIndexMetadataCollection: IndexMetadataEntity[]; createdIndexMetadataCollection: IndexMetadataEntity[];
}> { }> {
const indexMetadataRepository = manager.getRepository(IndexMetadataEntity); const indexMetadataRepository = manager.getRepository(IndexMetadataEntity);
const workspaceId = originalObjectMetadataCollection?.[0]?.workspaceId;
let isNewRelationEnabled = false;
if (workspaceId) {
isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
workspaceId,
);
}
const convertIndexMetadataForSaving = ( const convertIndexMetadataForSaving = (
indexMetadata: PartialIndexMetadata, indexMetadata: PartialIndexMetadata,
@ -391,7 +381,6 @@ export class WorkspaceMetadataUpdaterService {
.find((object) => object.id === indexMetadata.objectMetadataId) .find((object) => object.id === indexMetadata.objectMetadataId)
?.fields.find((field) => { ?.fields.find((field) => {
if ( if (
isNewRelationEnabled &&
isFieldMetadataEntityOfType(field, FieldMetadataType.RELATION) isFieldMetadataEntityOfType(field, FieldMetadataType.RELATION)
) { ) {
if (field.settings?.joinColumnName === column) { if (field.settings?.joinColumnName === column) {

View File

@ -1,5 +1,3 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { import {
ComputedPartialFieldMetadata, ComputedPartialFieldMetadata,
PartialComputedFieldMetadata, PartialComputedFieldMetadata,
@ -7,12 +5,8 @@ import {
} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface'; } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface';
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface'; import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { import { createRelationDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
createForeignKeyDeterministicUuid,
createRelationDeterministicUuid,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
export const computeStandardFields = ( export const computeStandardFields = (
context: WorkspaceSyncContext, context: WorkspaceSyncContext,
@ -25,9 +19,6 @@ export const computeStandardFields = (
): ComputedPartialFieldMetadata[] => { ): ComputedPartialFieldMetadata[] => {
const fields: ComputedPartialFieldMetadata[] = []; const fields: ComputedPartialFieldMetadata[] = [];
const isNewRelationEnabled =
context.featureFlags[FeatureFlagKey.IsNewRelationEnabled];
for (const partialFieldMetadata of standardFieldMetadataCollection) { for (const partialFieldMetadata of standardFieldMetadataCollection) {
// Relation from standard object to custom object // Relation from standard object to custom object
if ('argsFactory' in partialFieldMetadata) { if ('argsFactory' in partialFieldMetadata) {
@ -39,10 +30,6 @@ export const computeStandardFields = (
objectId: customObjectMetadata.id, objectId: customObjectMetadata.id,
standardId: data.standardId, standardId: data.standardId,
}); });
const foreignKeyStandardId = createForeignKeyDeterministicUuid({
objectId: customObjectMetadata.id,
standardId: data.standardId,
});
if (!joinColumn) { if (!joinColumn) {
throw new Error( throw new Error(
@ -57,23 +44,6 @@ export const computeStandardFields = (
standardId: relationStandardId, standardId: relationStandardId,
defaultValue: null, defaultValue: null,
}); });
// Only add foreign key if new relation is disabled
// As new relation will no longer create the field metadata related to foreign key
if (!isNewRelationEnabled) {
// Foreign key
fields.push({
...rest,
standardId: foreignKeyStandardId,
name: joinColumn,
type: FieldMetadataType.UUID,
label: `${data.label} ID (foreign key)`,
description: `${data.description} id foreign key`,
defaultValue: null,
icon: undefined,
isSystem: true,
});
}
} }
} else { } else {
// Relation from standard object to standard object // Relation from standard object to standard object

View File

@ -5,7 +5,6 @@ import { DataSource, QueryFailedError } from 'typeorm';
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface'; import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
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 { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service';
import { import {
@ -70,12 +69,6 @@ export class WorkspaceSyncMetadataService {
const manager = queryRunner.manager; const manager = queryRunner.manager;
try { try {
const isNewRelationEnabled =
await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
context.workspaceId,
);
const workspaceMigrationRepository = manager.getRepository( const workspaceMigrationRepository = manager.getRepository(
WorkspaceMigrationEntity, WorkspaceMigrationEntity,
); );
@ -127,21 +120,12 @@ export class WorkspaceSyncMetadataService {
let workspaceRelationMigrations: Partial<WorkspaceMigrationEntity>[] = []; let workspaceRelationMigrations: Partial<WorkspaceMigrationEntity>[] = [];
if (isNewRelationEnabled) { workspaceRelationMigrations =
workspaceRelationMigrations = await this.workspaceSyncFieldMetadataRelationService.synchronize(
await this.workspaceSyncFieldMetadataRelationService.synchronize( context,
context, manager,
manager, storage,
storage, );
);
} else {
workspaceRelationMigrations =
await this.workspaceSyncRelationMetadataService.synchronize(
context,
manager,
storage,
);
}
const workspaceRelationMigrationsEnd = performance.now(); const workspaceRelationMigrationsEnd = performance.now();
@ -149,24 +133,22 @@ export class WorkspaceSyncMetadataService {
`Workspace relation migrations took ${workspaceRelationMigrationsEnd - workspaceRelationMigrationsStart}ms`, `Workspace relation migrations took ${workspaceRelationMigrationsEnd - workspaceRelationMigrationsStart}ms`,
); );
let workspaceIndexMigrations: Partial<WorkspaceMigrationEntity>[] = []; const workspaceIndexMigrations: Partial<WorkspaceMigrationEntity>[] = [];
// 4 - Sync standard indexes on standard objects // 4 - Sync standard indexes on standard objects
if (!isNewRelationEnabled) { const workspaceIndexMigrationsStart = performance.now();
const workspaceIndexMigrationsStart = performance.now();
workspaceIndexMigrations = // workspaceIndexMigrations =
await this.workspaceSyncIndexMetadataService.synchronize( // await this.workspaceSyncIndexMetadataService.synchronize(
context, // context,
manager, // manager,
storage, // storage,
); // );
const workspaceIndexMigrationsEnd = performance.now(); const workspaceIndexMigrationsEnd = performance.now();
this.logger.log( this.logger.log(
`Workspace index migrations took ${workspaceIndexMigrationsEnd - workspaceIndexMigrationsStart}ms`, `Workspace index migrations took ${workspaceIndexMigrationsEnd - workspaceIndexMigrationsStart}ms`,
); );
}
// 5 - Sync standard object metadata identifiers, does not need to return nor apply migrations // 5 - Sync standard object metadata identifiers, does not need to return nor apply migrations
const workspaceObjectMetadataIdentifiersStart = performance.now(); const workspaceObjectMetadataIdentifiersStart = performance.now();

View File

@ -12,8 +12,6 @@ import { WorkflowExecutor } from 'src/modules/workflow/workflow-executor/interfa
import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant'; import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant';
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser'; import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
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 { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory'; import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
@ -40,7 +38,6 @@ export class FindRecordsWorkflowAction implements WorkflowExecutor {
constructor( constructor(
private readonly twentyORMManager: TwentyORMManager, private readonly twentyORMManager: TwentyORMManager,
private readonly scopedWorkspaceContextFactory: ScopedWorkspaceContextFactory, private readonly scopedWorkspaceContextFactory: ScopedWorkspaceContextFactory,
private readonly featureFlagService: FeatureFlagService,
private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService, private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService,
) {} ) {}
@ -89,14 +86,10 @@ export class FindRecordsWorkflowAction implements WorkflowExecutor {
workspaceId, workspaceId,
); );
const featureFlagMaps =
await this.featureFlagService.getWorkspaceFeatureFlagsMap(workspaceId);
const graphqlQueryParser = new GraphqlQueryParser( const graphqlQueryParser = new GraphqlQueryParser(
objectMetadataItemWithFieldsMaps.fieldsByName, objectMetadataItemWithFieldsMaps.fieldsByName,
objectMetadataItemWithFieldsMaps.fieldsByJoinColumnName, objectMetadataItemWithFieldsMaps.fieldsByJoinColumnName,
objectMetadataMaps, objectMetadataMaps,
featureFlagMaps,
); );
const objectRecords = await this.getObjectRecords( const objectRecords = await this.getObjectRecords(
@ -129,11 +122,6 @@ export class FindRecordsWorkflowAction implements WorkflowExecutor {
repository: WorkspaceRepository<T>, repository: WorkspaceRepository<T>,
graphqlQueryParser: GraphqlQueryParser, graphqlQueryParser: GraphqlQueryParser,
) { ) {
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
objectMetadataItemWithFieldsMaps.workspaceId,
);
const queryBuilder = repository.createQueryBuilder( const queryBuilder = repository.createQueryBuilder(
workflowActionInput.objectName, workflowActionInput.objectName,
); );
@ -164,7 +152,6 @@ export class FindRecordsWorkflowAction implements WorkflowExecutor {
nonFormattedObjectRecords, nonFormattedObjectRecords,
objectMetadataItemWithFieldsMaps, objectMetadataItemWithFieldsMaps,
objectMetadataMaps, objectMetadataMaps,
isNewRelationEnabled,
); );
} }

View File

@ -2,7 +2,6 @@ import { Module } from '@nestjs/common';
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { RecordPositionModule } from 'src/engine/core-modules/record-position/record-position.module'; import { RecordPositionModule } from 'src/engine/core-modules/record-position/record-position.module';
import { RecordTransformerModule } from 'src/engine/core-modules/record-transformer/record-transformer.module'; import { RecordTransformerModule } from 'src/engine/core-modules/record-transformer/record-transformer.module';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
@ -18,7 +17,6 @@ import { UpdateRecordWorkflowAction } from 'src/modules/workflow/workflow-execut
imports: [ imports: [
WorkspaceCacheStorageModule, WorkspaceCacheStorageModule,
NestjsQueryTypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'), NestjsQueryTypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'),
FeatureFlagModule,
RecordPositionModule, RecordPositionModule,
RecordTransformerModule, RecordTransformerModule,
WorkflowCommonModule, WorkflowCommonModule,