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:
@ -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',
|
||||||
|
|||||||
@ -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',
|
||||||
|
|||||||
@ -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({
|
||||||
|
|||||||
@ -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();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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(
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -324,7 +324,6 @@ export class ProcessNestedRelationsV2Helper {
|
|||||||
result,
|
result,
|
||||||
targetObjectMetadata,
|
targetObjectMetadata,
|
||||||
objectMetadataMaps,
|
objectMetadataMaps,
|
||||||
true,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return { relationResults, relationAggregatedFieldsResult };
|
return { relationResults, relationAggregatedFieldsResult };
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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({
|
||||||
|
|||||||
@ -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],
|
||||||
|
|||||||
@ -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({
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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({
|
||||||
|
|||||||
@ -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],
|
||||||
|
|||||||
@ -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({
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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],
|
||||||
|
|||||||
@ -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({
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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({
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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;
|
|
||||||
};
|
|
||||||
@ -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,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -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,
|
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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 =
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 {}
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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(
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -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)) {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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({
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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];
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user