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:
@ -6,7 +6,6 @@ import {
|
||||
} from 'typeorm';
|
||||
|
||||
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';
|
||||
|
||||
@ -20,14 +19,12 @@ export class GraphqlQueryFilterConditionParser {
|
||||
constructor(
|
||||
fieldMetadataMapByName: FieldMetadataMap,
|
||||
fieldMetadataMapByJoinColumnName: FieldMetadataMap,
|
||||
featureFlagsMap: FeatureFlagMap,
|
||||
) {
|
||||
this.fieldMetadataMapByName = fieldMetadataMapByName;
|
||||
this.fieldMetadataMapByJoinColumnName = fieldMetadataMapByJoinColumnName;
|
||||
this.queryFilterFieldParser = new GraphqlQueryFilterFieldParser(
|
||||
this.fieldMetadataMapByName,
|
||||
this.fieldMetadataMapByJoinColumnName,
|
||||
featureFlagsMap,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ import { capitalize } from 'twenty-shared/utils';
|
||||
import { WhereExpressionBuilder } from 'typeorm';
|
||||
|
||||
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 {
|
||||
GraphqlQueryRunnerException,
|
||||
@ -19,16 +18,13 @@ const ARRAY_OPERATORS = ['in', 'contains', 'notContains'];
|
||||
export class GraphqlQueryFilterFieldParser {
|
||||
private fieldMetadataMapByName: FieldMetadataMap;
|
||||
private fieldMetadataMapByJoinColumnName: FieldMetadataMap;
|
||||
private featureFlagsMap: FeatureFlagMap;
|
||||
|
||||
constructor(
|
||||
fieldMetadataMapByName: FieldMetadataMap,
|
||||
fieldMetadataMapByJoinColumnName: FieldMetadataMap,
|
||||
featureFlagsMap: FeatureFlagMap,
|
||||
) {
|
||||
this.fieldMetadataMapByName = fieldMetadataMapByName;
|
||||
this.fieldMetadataMapByJoinColumnName = fieldMetadataMapByJoinColumnName;
|
||||
this.featureFlagsMap = featureFlagsMap;
|
||||
}
|
||||
|
||||
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 {
|
||||
GraphqlQuerySelectedFieldsParser,
|
||||
GraphqlQuerySelectedFieldsResult,
|
||||
} 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 { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
||||
|
||||
export class GraphqlQuerySelectedFieldsRelationParser {
|
||||
private objectMetadataMaps: ObjectMetadataMaps;
|
||||
private featureFlagsMap: FeatureFlagMap;
|
||||
|
||||
constructor(
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
featureFlagsMap: FeatureFlagMap,
|
||||
) {
|
||||
constructor(objectMetadataMaps: ObjectMetadataMaps) {
|
||||
this.objectMetadataMaps = objectMetadataMaps;
|
||||
this.featureFlagsMap = featureFlagsMap;
|
||||
}
|
||||
|
||||
parseRelationField(
|
||||
@ -34,17 +26,14 @@ export class GraphqlQuerySelectedFieldsRelationParser {
|
||||
|
||||
accumulator.relations[fieldKey] = true;
|
||||
|
||||
const isNewRelationEnabled =
|
||||
this.featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled];
|
||||
|
||||
const targetObjectMetadata = isNewRelationEnabled
|
||||
? getTargetObjectMetadataOrThrow(fieldMetadata, this.objectMetadataMaps)
|
||||
: getRelationObjectMetadata(fieldMetadata, this.objectMetadataMaps);
|
||||
const targetObjectMetadata = getTargetObjectMetadataOrThrow(
|
||||
fieldMetadata,
|
||||
this.objectMetadataMaps,
|
||||
);
|
||||
|
||||
const targetFields = targetObjectMetadata.fieldsByName;
|
||||
const fieldParser = new GraphqlQuerySelectedFieldsParser(
|
||||
this.objectMetadataMaps,
|
||||
this.featureFlagsMap,
|
||||
);
|
||||
const relationAccumulator = fieldParser.parse(fieldValue, targetFields);
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
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 { 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 aggregateParser: GraphqlQuerySelectedFieldsAggregateParser;
|
||||
|
||||
constructor(
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
featureFlagsMap: FeatureFlagMap,
|
||||
) {
|
||||
constructor(objectMetadataMaps: ObjectMetadataMaps) {
|
||||
this.graphqlQuerySelectedFieldsRelationParser =
|
||||
new GraphqlQuerySelectedFieldsRelationParser(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new GraphqlQuerySelectedFieldsRelationParser(objectMetadataMaps);
|
||||
this.aggregateParser = new GraphqlQuerySelectedFieldsAggregateParser();
|
||||
}
|
||||
|
||||
|
||||
@ -9,8 +9,11 @@ import {
|
||||
ObjectRecordFilter,
|
||||
ObjectRecordOrderBy,
|
||||
} 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 { GraphqlQueryOrderFieldParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-order/graphql-query-order.parser';
|
||||
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 { 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 {
|
||||
GraphqlQueryRunnerException,
|
||||
GraphqlQueryRunnerExceptionCode,
|
||||
} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
|
||||
|
||||
export class GraphqlQueryParser {
|
||||
private fieldMetadataMapByName: FieldMetadataMap;
|
||||
@ -32,22 +31,18 @@ export class GraphqlQueryParser {
|
||||
private objectMetadataMaps: ObjectMetadataMaps;
|
||||
private filterConditionParser: GraphqlQueryFilterConditionParser;
|
||||
private orderFieldParser: GraphqlQueryOrderFieldParser;
|
||||
private featureFlagsMap: FeatureFlagMap;
|
||||
|
||||
constructor(
|
||||
fieldMetadataMapByName: FieldMetadataMap,
|
||||
fieldMetadataMapByJoinColumnName: FieldMetadataMap,
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
featureFlagsMap: FeatureFlagMap,
|
||||
) {
|
||||
this.objectMetadataMaps = objectMetadataMaps;
|
||||
this.fieldMetadataMapByName = fieldMetadataMapByName;
|
||||
this.fieldMetadataMapByJoinColumnName = fieldMetadataMapByJoinColumnName;
|
||||
this.featureFlagsMap = featureFlagsMap;
|
||||
this.filterConditionParser = new GraphqlQueryFilterConditionParser(
|
||||
this.fieldMetadataMapByName,
|
||||
this.fieldMetadataMapByJoinColumnName,
|
||||
featureFlagsMap,
|
||||
);
|
||||
this.orderFieldParser = new GraphqlQueryOrderFieldParser(
|
||||
this.fieldMetadataMapByName,
|
||||
@ -136,7 +131,6 @@ export class GraphqlQueryParser {
|
||||
|
||||
const selectedFieldsParser = new GraphqlQuerySelectedFieldsParser(
|
||||
this.objectMetadataMaps,
|
||||
this.featureFlagsMap,
|
||||
);
|
||||
|
||||
return selectedFieldsParser.parse(graphqlSelectedFields, parentFields);
|
||||
|
||||
@ -6,7 +6,6 @@ import {
|
||||
ObjectRecordOrderBy,
|
||||
} 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 { 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 { CONNECTION_MAX_DEPTH } from 'src/engine/api/graphql/graphql-query-runner/constants/connection-max-depth.constant';
|
||||
@ -15,10 +14,8 @@ import {
|
||||
GraphqlQueryRunnerExceptionCode,
|
||||
} 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 { 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 { 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 { 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';
|
||||
@ -29,14 +26,9 @@ import { isPlainObject } from 'src/utils/is-plain-object';
|
||||
|
||||
export class ObjectRecordsToGraphqlConnectionHelper {
|
||||
private objectMetadataMaps: ObjectMetadataMaps;
|
||||
private featureFlagsMap: FeatureFlagMap;
|
||||
|
||||
constructor(
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
featureFlagsMap: FeatureFlagMap,
|
||||
) {
|
||||
constructor(objectMetadataMaps: ObjectMetadataMaps) {
|
||||
this.objectMetadataMaps = objectMetadataMaps;
|
||||
this.featureFlagsMap = featureFlagsMap;
|
||||
}
|
||||
|
||||
public createConnection<T extends ObjectRecord = ObjectRecord>({
|
||||
@ -154,9 +146,6 @@ export class ObjectRecordsToGraphqlConnectionHelper {
|
||||
);
|
||||
}
|
||||
|
||||
const isNewRelationEnabled =
|
||||
this.featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled];
|
||||
|
||||
const objectMetadata = getObjectMetadataMapItemByNameSingular(
|
||||
this.objectMetadataMaps,
|
||||
objectName,
|
||||
@ -181,12 +170,10 @@ export class ObjectRecordsToGraphqlConnectionHelper {
|
||||
|
||||
if (isRelationFieldMetadataType(fieldMetadata.type)) {
|
||||
if (Array.isArray(value)) {
|
||||
const targetObjectMetadata = isNewRelationEnabled
|
||||
? getTargetObjectMetadataOrThrow(
|
||||
fieldMetadata,
|
||||
this.objectMetadataMaps,
|
||||
)
|
||||
: getRelationObjectMetadata(fieldMetadata, this.objectMetadataMaps);
|
||||
const targetObjectMetadata = getTargetObjectMetadataOrThrow(
|
||||
fieldMetadata,
|
||||
this.objectMetadataMaps,
|
||||
);
|
||||
|
||||
processedObjectRecord[key] = this.createConnection({
|
||||
objectRecords: value,
|
||||
@ -206,12 +193,10 @@ export class ObjectRecordsToGraphqlConnectionHelper {
|
||||
depth: depth + 1,
|
||||
});
|
||||
} else if (isPlainObject(value)) {
|
||||
const targetObjectMetadata = isNewRelationEnabled
|
||||
? getTargetObjectMetadataOrThrow(
|
||||
fieldMetadata,
|
||||
this.objectMetadataMaps,
|
||||
)
|
||||
: getRelationObjectMetadata(fieldMetadata, this.objectMetadataMaps);
|
||||
const targetObjectMetadata = getTargetObjectMetadataOrThrow(
|
||||
fieldMetadata,
|
||||
this.objectMetadataMaps,
|
||||
);
|
||||
|
||||
processedObjectRecord[key] = this.processRecord({
|
||||
objectRecord: value,
|
||||
|
||||
@ -324,7 +324,6 @@ export class ProcessNestedRelationsV2Helper {
|
||||
result,
|
||||
targetObjectMetadata,
|
||||
objectMetadataMaps,
|
||||
true,
|
||||
);
|
||||
|
||||
return { relationResults, relationAggregatedFieldsResult };
|
||||
|
||||
@ -1,32 +1,16 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
DataSource,
|
||||
FindOptionsRelations,
|
||||
ObjectLiteral,
|
||||
SelectQueryBuilder,
|
||||
} from 'typeorm';
|
||||
import { FindOptionsRelations, ObjectLiteral } from 'typeorm';
|
||||
|
||||
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 { 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 { 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 { 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 { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
import { deduceRelationDirection } from 'src/engine/utils/deduce-relation-direction.util';
|
||||
|
||||
@Injectable()
|
||||
export class ProcessNestedRelationsHelper {
|
||||
@ -45,7 +29,6 @@ export class ProcessNestedRelationsHelper {
|
||||
limit,
|
||||
authContext,
|
||||
dataSource,
|
||||
isNewRelationEnabled,
|
||||
shouldBypassPermissionChecks,
|
||||
roleId,
|
||||
}: {
|
||||
@ -58,472 +41,21 @@ export class ProcessNestedRelationsHelper {
|
||||
limit: number;
|
||||
authContext: AuthContext;
|
||||
dataSource: WorkspaceDataSource;
|
||||
isNewRelationEnabled: boolean;
|
||||
shouldBypassPermissionChecks: boolean;
|
||||
roleId?: string;
|
||||
}): Promise<void> {
|
||||
if (isNewRelationEnabled) {
|
||||
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, {
|
||||
return this.processNestedRelationsV2Helper.processNestedRelations({
|
||||
objectMetadataMaps,
|
||||
parentObjectMetadataItem,
|
||||
parentObjectRecords,
|
||||
parentObjectRecordsAggregatedValues,
|
||||
relationName,
|
||||
nestedRelations,
|
||||
relations,
|
||||
aggregate,
|
||||
limit,
|
||||
authContext,
|
||||
dataSource,
|
||||
isNewRelationEnabled,
|
||||
shouldBypassPermissionChecks,
|
||||
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.fieldsByJoinColumnName,
|
||||
options.objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
|
||||
const selectedFields = graphqlFields(options.info);
|
||||
@ -170,7 +169,6 @@ export abstract class GraphqlQueryBaseResolverService<
|
||||
objectMetadataItemWithFieldMaps,
|
||||
authContext.workspace.id,
|
||||
options.objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
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 { 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 { 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 { 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';
|
||||
@ -30,7 +29,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<CreateManyResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord[]> {
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -44,7 +42,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
objectRecords,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitCreateEvents(
|
||||
@ -60,7 +57,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
upsertedRecords,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
shouldBypassPermissionChecks,
|
||||
roleId,
|
||||
);
|
||||
@ -69,7 +65,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
upsertedRecords,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
}
|
||||
|
||||
@ -305,7 +300,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
objectRecords: InsertResult,
|
||||
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord[]> {
|
||||
const queryBuilder = executionArgs.repository.createQueryBuilder(
|
||||
objectMetadataItemWithFieldMaps.nameSingular,
|
||||
@ -322,7 +316,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
nonFormattedUpsertedRecords,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
}
|
||||
|
||||
@ -331,7 +324,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
upsertedRecords: ObjectRecord[],
|
||||
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
shouldBypassPermissionChecks: boolean,
|
||||
roleId?: string,
|
||||
): Promise<void> {
|
||||
@ -347,8 +339,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext: executionArgs.options.authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks,
|
||||
});
|
||||
@ -358,13 +348,9 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
upsertedRecords: ObjectRecord[],
|
||||
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): ObjectRecord[] {
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return upsertedRecords.map((record: ObjectRecord) =>
|
||||
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 { 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 { 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 { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
|
||||
@ -24,7 +23,6 @@ export class GraphqlQueryCreateOneResolverService extends GraphqlQueryBaseResolv
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<CreateOneResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord> {
|
||||
const { authContext, objectMetadataMaps, objectMetadataItemWithFieldMaps } =
|
||||
executionArgs.options;
|
||||
@ -53,7 +51,6 @@ export class GraphqlQueryCreateOneResolverService extends GraphqlQueryBaseResolv
|
||||
nonFormattedUpsertedRecords,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitCreateEvents(
|
||||
@ -71,18 +68,13 @@ export class GraphqlQueryCreateOneResolverService extends GraphqlQueryBaseResolv
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
|
||||
});
|
||||
}
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
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 { 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 { 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 { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
import { computeTableName } from 'src/engine/utils/compute-table-name.util';
|
||||
@ -23,7 +22,6 @@ export class GraphqlQueryDeleteManyResolverService extends GraphqlQueryBaseResol
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<DeleteManyResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord[]> {
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -54,7 +52,6 @@ export class GraphqlQueryDeleteManyResolverService extends GraphqlQueryBaseResol
|
||||
nonFormattedDeletedObjectRecords.raw,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitDeletedEvents(
|
||||
@ -72,18 +69,13 @@ export class GraphqlQueryDeleteManyResolverService extends GraphqlQueryBaseResol
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
|
||||
});
|
||||
}
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return formattedDeletedRecords.map((record: ObjectRecord) =>
|
||||
typeORMObjectRecordsParser.processRecord({
|
||||
|
||||
@ -15,7 +15,6 @@ import {
|
||||
} 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 { 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 { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
|
||||
@ -26,7 +25,6 @@ export class GraphqlQueryDeleteOneResolverService extends GraphqlQueryBaseResolv
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<DeleteOneResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord> {
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -47,7 +45,6 @@ export class GraphqlQueryDeleteOneResolverService extends GraphqlQueryBaseResolv
|
||||
nonFormattedDeletedObjectRecords.raw,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitDeletedEvents(
|
||||
@ -74,18 +71,13 @@ export class GraphqlQueryDeleteOneResolverService extends GraphqlQueryBaseResolv
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
|
||||
});
|
||||
}
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
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 { 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 { computeTableName } from 'src/engine/utils/compute-table-name.util';
|
||||
|
||||
@ -21,7 +20,6 @@ export class GraphqlQueryDestroyManyResolverService extends GraphqlQueryBaseReso
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<DestroyManyResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord[]> {
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -52,7 +50,6 @@ export class GraphqlQueryDestroyManyResolverService extends GraphqlQueryBaseReso
|
||||
nonFormattedDeletedObjectRecords.raw,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitDestroyEvents(
|
||||
@ -70,18 +67,13 @@ export class GraphqlQueryDestroyManyResolverService extends GraphqlQueryBaseReso
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
|
||||
});
|
||||
}
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return deletedRecords.map((record: ObjectRecord) =>
|
||||
typeORMObjectRecordsParser.processRecord({
|
||||
|
||||
@ -14,7 +14,6 @@ import {
|
||||
GraphqlQueryRunnerExceptionCode,
|
||||
} 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 { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
|
||||
@Injectable()
|
||||
@ -24,7 +23,6 @@ export class GraphqlQueryDestroyOneResolverService extends GraphqlQueryBaseResol
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<DestroyOneResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord> {
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -52,7 +50,6 @@ export class GraphqlQueryDestroyOneResolverService extends GraphqlQueryBaseResol
|
||||
nonFormattedDeletedObjectRecords.raw,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitDestroyEvents(
|
||||
@ -70,18 +67,13 @@ export class GraphqlQueryDestroyOneResolverService extends GraphqlQueryBaseResol
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
|
||||
});
|
||||
}
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
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 { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
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 { 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';
|
||||
@ -39,7 +38,6 @@ export class GraphqlQueryFindDuplicatesResolverService extends GraphqlQueryBaseR
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<FindDuplicatesResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<IConnection<ObjectRecord>[]> {
|
||||
const { objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -66,14 +64,10 @@ export class GraphqlQueryFindDuplicatesResolverService extends GraphqlQueryBaseR
|
||||
objectMetadataItemWithFieldsMaps?.fieldsByName,
|
||||
objectMetadataItemWithFieldsMaps?.fieldsByJoinColumnName,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
let objectRecords: Partial<ObjectRecord>[] = [];
|
||||
|
||||
@ -86,7 +80,6 @@ export class GraphqlQueryFindDuplicatesResolverService extends GraphqlQueryBaseR
|
||||
nonFormattedObjectRecords,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
} else if (executionArgs.args.data && !isEmpty(executionArgs.args.data)) {
|
||||
objectRecords = formatData(
|
||||
@ -133,7 +126,6 @@ export class GraphqlQueryFindDuplicatesResolverService extends GraphqlQueryBaseR
|
||||
nonFormattedDuplicates,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
return typeORMObjectRecordsParser.createConnection({
|
||||
|
||||
@ -28,7 +28,6 @@ import {
|
||||
getCursor,
|
||||
getPaginationInfo,
|
||||
} 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';
|
||||
|
||||
@Injectable()
|
||||
@ -42,7 +41,6 @@ export class GraphqlQueryFindManyResolverService extends GraphqlQueryBaseResolve
|
||||
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<FindManyResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<IConnection<ObjectRecord>> {
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -130,7 +128,6 @@ export class GraphqlQueryFindManyResolverService extends GraphqlQueryBaseResolve
|
||||
nonFormattedObjectRecords,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
const { hasNextPage, hasPreviousPage } = getPaginationInfo(
|
||||
@ -157,18 +154,13 @@ export class GraphqlQueryFindManyResolverService extends GraphqlQueryBaseResolve
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
|
||||
});
|
||||
}
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return typeORMObjectRecordsParser.createConnection({
|
||||
objectRecords,
|
||||
|
||||
@ -21,7 +21,6 @@ import {
|
||||
WorkspaceQueryRunnerException,
|
||||
WorkspaceQueryRunnerExceptionCode,
|
||||
} 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';
|
||||
|
||||
@Injectable()
|
||||
@ -31,7 +30,6 @@ export class GraphqlQueryFindOneResolverService extends GraphqlQueryBaseResolver
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<FindOneResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord> {
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -59,7 +57,6 @@ export class GraphqlQueryFindOneResolverService extends GraphqlQueryBaseResolver
|
||||
nonFormattedObjectRecord,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
if (!objectRecord) {
|
||||
@ -80,18 +77,13 @@ export class GraphqlQueryFindOneResolverService extends GraphqlQueryBaseResolver
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
|
||||
});
|
||||
}
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
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 { 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 { 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 { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
import { computeTableName } from 'src/engine/utils/compute-table-name.util';
|
||||
@ -23,7 +22,6 @@ export class GraphqlQueryRestoreManyResolverService extends GraphqlQueryBaseReso
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<RestoreManyResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord[]> {
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -54,7 +52,6 @@ export class GraphqlQueryRestoreManyResolverService extends GraphqlQueryBaseReso
|
||||
nonFormattedRestoredObjectRecords.raw,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitRestoreEvents(
|
||||
@ -72,18 +69,13 @@ export class GraphqlQueryRestoreManyResolverService extends GraphqlQueryBaseReso
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
|
||||
});
|
||||
}
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return formattedRestoredRecords.map((record: ObjectRecord) =>
|
||||
typeORMObjectRecordsParser.processRecord({
|
||||
|
||||
@ -15,7 +15,6 @@ import {
|
||||
} 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 { 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 { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
|
||||
@ -26,7 +25,6 @@ export class GraphqlQueryRestoreOneResolverService extends GraphqlQueryBaseResol
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<RestoreOneResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord> {
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -47,7 +45,6 @@ export class GraphqlQueryRestoreOneResolverService extends GraphqlQueryBaseResol
|
||||
nonFormattedRestoredObjectRecords.raw,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitRestoreEvents(
|
||||
@ -74,18 +71,13 @@ export class GraphqlQueryRestoreOneResolverService extends GraphqlQueryBaseResol
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
|
||||
});
|
||||
}
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: restoredRecord,
|
||||
|
||||
@ -17,7 +17,6 @@ import {
|
||||
} 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 { 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 { formatData } from 'src/engine/twenty-orm/utils/format-data.util';
|
||||
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
@ -30,7 +29,6 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<UpdateManyResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord[]> {
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -55,7 +53,6 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
|
||||
existingRecords,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
if (isEmpty(formattedExistingRecords)) {
|
||||
@ -90,7 +87,6 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
|
||||
nonFormattedUpdatedObjectRecords.raw,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitUpdateEvents(
|
||||
@ -110,18 +106,13 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
|
||||
});
|
||||
}
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return formattedUpdatedRecords.map((record: ObjectRecord) =>
|
||||
typeORMObjectRecordsParser.processRecord({
|
||||
|
||||
@ -17,7 +17,6 @@ import {
|
||||
} 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 { 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 { formatData } from 'src/engine/twenty-orm/utils/format-data.util';
|
||||
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||
@ -29,7 +28,6 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
|
||||
> {
|
||||
async resolve(
|
||||
executionArgs: GraphqlQueryResolverExecutionArgs<UpdateOneResolverArgs>,
|
||||
featureFlagsMap: Record<FeatureFlagKey, boolean>,
|
||||
): Promise<ObjectRecord> {
|
||||
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
|
||||
executionArgs.options;
|
||||
@ -55,7 +53,6 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
|
||||
existingRecords,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
if (isEmpty(formattedExistingRecords)) {
|
||||
@ -75,7 +72,6 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
|
||||
nonFormattedUpdatedObjectRecords.raw,
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
);
|
||||
|
||||
this.apiEventEmitterService.emitUpdateEvents(
|
||||
@ -104,18 +100,13 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
|
||||
limit: QUERY_MAX_RECORDS,
|
||||
authContext,
|
||||
dataSource: executionArgs.dataSource,
|
||||
isNewRelationEnabled:
|
||||
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
roleId,
|
||||
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
|
||||
});
|
||||
}
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
objectMetadataMaps,
|
||||
featureFlagsMap,
|
||||
);
|
||||
new ObjectRecordsToGraphqlConnectionHelper(objectMetadataMaps);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
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,
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
workspaceId: string,
|
||||
isNewRelationEnabled: boolean,
|
||||
): Promise<IConnection<ObjectRecord>> {
|
||||
return {
|
||||
...connection,
|
||||
@ -83,7 +82,6 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItemId,
|
||||
objectMetadataMaps,
|
||||
workspaceId,
|
||||
isNewRelationEnabled,
|
||||
),
|
||||
})),
|
||||
),
|
||||
@ -95,7 +93,6 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItemId: string,
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
workspaceId: string,
|
||||
isNewRelationEnabled: boolean,
|
||||
) {
|
||||
return {
|
||||
...result,
|
||||
@ -107,7 +104,6 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItemId,
|
||||
objectMetadataMaps,
|
||||
workspaceId,
|
||||
isNewRelationEnabled,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -119,7 +115,6 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItemId: string,
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
workspaceId: string,
|
||||
isNewRelationEnabled: boolean,
|
||||
) {
|
||||
return await Promise.all(
|
||||
recordArray.map(
|
||||
@ -129,7 +124,6 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItemId,
|
||||
objectMetadataMaps,
|
||||
workspaceId,
|
||||
isNewRelationEnabled,
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -140,7 +134,6 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItemId: string,
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
workspaceId: string,
|
||||
isNewRelationEnabled: boolean,
|
||||
): Promise<ObjectRecord> {
|
||||
const objectMetadataMapItem = objectMetadataMaps.byId[objectMetadataItemId];
|
||||
|
||||
@ -165,55 +158,17 @@ export class QueryResultGettersFactory {
|
||||
>;
|
||||
|
||||
for (const relationField of relationFields) {
|
||||
if (!isNewRelationEnabled) {
|
||||
const relationMetadata =
|
||||
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,
|
||||
);
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
const objectRecordProcessedWithoutRelationFields = await handler.handle(
|
||||
@ -234,7 +189,6 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItemId: string,
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
workspaceId: string,
|
||||
isNewRelationEnabled: boolean,
|
||||
) {
|
||||
if (isQueryResultFieldValueAConnection(queryResultField)) {
|
||||
return await this.processConnection(
|
||||
@ -242,7 +196,6 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItemId,
|
||||
objectMetadataMaps,
|
||||
workspaceId,
|
||||
isNewRelationEnabled,
|
||||
);
|
||||
} else if (isQueryResultFieldValueANestedRecordArray(queryResultField)) {
|
||||
return await this.processNestedRecordArray(
|
||||
@ -250,7 +203,6 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItemId,
|
||||
objectMetadataMaps,
|
||||
workspaceId,
|
||||
isNewRelationEnabled,
|
||||
);
|
||||
} else if (isQueryResultFieldValueARecordArray(queryResultField)) {
|
||||
return await this.processRecordArray(
|
||||
@ -258,7 +210,6 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItemId,
|
||||
objectMetadataMaps,
|
||||
workspaceId,
|
||||
isNewRelationEnabled,
|
||||
);
|
||||
} else if (isQueryResultFieldValueARecord(queryResultField)) {
|
||||
return await this.processRecord(
|
||||
@ -266,7 +217,6 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItemId,
|
||||
objectMetadataMaps,
|
||||
workspaceId,
|
||||
isNewRelationEnabled,
|
||||
);
|
||||
} else {
|
||||
this.logger.warn(
|
||||
@ -283,14 +233,12 @@ export class QueryResultGettersFactory {
|
||||
objectMetadataItem: ObjectMetadataInterface,
|
||||
workspaceId: string,
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
isNewRelationEnabled: boolean,
|
||||
): Promise<any> {
|
||||
return await this.processQueryResultField(
|
||||
result,
|
||||
objectMetadataItem.id,
|
||||
objectMetadataMaps,
|
||||
workspaceId,
|
||||
isNewRelationEnabled,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -36,7 +36,6 @@ export class InputTypeDefinitionFactory {
|
||||
objectMetadata: ObjectMetadataInterface,
|
||||
kind: InputTypeDefinitionKind,
|
||||
options: WorkspaceBuildSchemaOptions,
|
||||
isNewRelationEnabled = false,
|
||||
): InputTypeDefinition {
|
||||
const inputType = new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${kind.toString()}Input`,
|
||||
@ -59,7 +58,6 @@ export class InputTypeDefinitionFactory {
|
||||
kind,
|
||||
options,
|
||||
this.inputTypeFactory,
|
||||
isNewRelationEnabled,
|
||||
),
|
||||
and: {
|
||||
type: andOrType,
|
||||
@ -83,7 +81,6 @@ export class InputTypeDefinitionFactory {
|
||||
kind,
|
||||
options,
|
||||
this.inputTypeFactory,
|
||||
isNewRelationEnabled,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@ -30,7 +30,6 @@ export class ObjectTypeDefinitionFactory {
|
||||
objectMetadata: ObjectMetadataInterface,
|
||||
kind: ObjectTypeDefinitionKind,
|
||||
options: WorkspaceBuildSchemaOptions,
|
||||
isNewRelationEnabled = false,
|
||||
): ObjectTypeDefinition {
|
||||
return {
|
||||
target: objectMetadata.id,
|
||||
@ -43,7 +42,6 @@ export class ObjectTypeDefinitionFactory {
|
||||
kind,
|
||||
options,
|
||||
this.outputTypeFactory,
|
||||
isNewRelationEnabled,
|
||||
),
|
||||
}),
|
||||
};
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import chalk from 'chalk';
|
||||
|
||||
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';
|
||||
|
||||
@ -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 { 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 { 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 { ConnectionTypeDefinitionFactory } from './factories/connection-type-definition.factory';
|
||||
import { EdgeTypeDefinitionFactory } from './factories/edge-type-definition.factory';
|
||||
import { ExtendObjectTypeDefinitionFactory } from './factories/extend-object-type-definition.factory';
|
||||
import {
|
||||
InputTypeDefinitionFactory,
|
||||
InputTypeDefinitionKind,
|
||||
@ -43,24 +38,17 @@ export class TypeDefinitionsGenerator {
|
||||
private readonly compositeInputTypeDefinitionFactory: CompositeInputTypeDefinitionFactory,
|
||||
private readonly edgeTypeDefinitionFactory: EdgeTypeDefinitionFactory,
|
||||
private readonly connectionTypeDefinitionFactory: ConnectionTypeDefinitionFactory,
|
||||
private readonly extendObjectTypeDefinitionFactory: ExtendObjectTypeDefinitionFactory,
|
||||
private readonly extendObjectTypeDefinitionV2Factory: ExtendObjectTypeDefinitionV2Factory,
|
||||
private readonly featureFlagService: FeatureFlagService,
|
||||
) {}
|
||||
|
||||
async generate(
|
||||
objectMetadataCollection: ObjectMetadataInterface[],
|
||||
options: WorkspaceBuildSchemaOptions,
|
||||
isNewRelationEnabled: boolean,
|
||||
) {
|
||||
// Generate composite type objects first because they can be used in dynamic objects
|
||||
await this.generateCompositeTypeDefs(options);
|
||||
// Generate metadata objects
|
||||
await this.generateMetadataTypeDefs(
|
||||
objectMetadataCollection,
|
||||
options,
|
||||
isNewRelationEnabled,
|
||||
);
|
||||
await this.generateMetadataTypeDefs(objectMetadataCollection, options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -160,7 +148,6 @@ export class TypeDefinitionsGenerator {
|
||||
private async generateMetadataTypeDefs(
|
||||
dynamicObjectMetadataCollection: ObjectMetadataInterface[],
|
||||
options: WorkspaceBuildSchemaOptions,
|
||||
isNewRelationEnabled: boolean,
|
||||
) {
|
||||
this.logger.log(
|
||||
`Generating metadata objects: [${dynamicObjectMetadataCollection
|
||||
@ -170,17 +157,9 @@ export class TypeDefinitionsGenerator {
|
||||
|
||||
// Generate dynamic objects
|
||||
this.generateEnumTypeDefs(dynamicObjectMetadataCollection, options);
|
||||
this.generateObjectTypeDefs(
|
||||
dynamicObjectMetadataCollection,
|
||||
options,
|
||||
isNewRelationEnabled,
|
||||
);
|
||||
this.generateObjectTypeDefs(dynamicObjectMetadataCollection, options);
|
||||
this.generatePaginationTypeDefs(dynamicObjectMetadataCollection, options);
|
||||
this.generateInputTypeDefs(
|
||||
dynamicObjectMetadataCollection,
|
||||
options,
|
||||
isNewRelationEnabled,
|
||||
);
|
||||
this.generateInputTypeDefs(dynamicObjectMetadataCollection, options);
|
||||
await this.generateExtendedObjectTypeDefs(
|
||||
dynamicObjectMetadataCollection,
|
||||
options,
|
||||
@ -190,14 +169,12 @@ export class TypeDefinitionsGenerator {
|
||||
private generateObjectTypeDefs(
|
||||
objectMetadataCollection: ObjectMetadataInterface[] | CompositeType[],
|
||||
options: WorkspaceBuildSchemaOptions,
|
||||
isNewRelationEnabled: boolean,
|
||||
) {
|
||||
const objectTypeDefs = objectMetadataCollection.map((objectMetadata) =>
|
||||
this.objectTypeDefinitionFactory.create(
|
||||
objectMetadata,
|
||||
ObjectTypeDefinitionKind.Plain,
|
||||
options,
|
||||
isNewRelationEnabled,
|
||||
),
|
||||
);
|
||||
|
||||
@ -225,7 +202,6 @@ export class TypeDefinitionsGenerator {
|
||||
private generateInputTypeDefs(
|
||||
objectMetadataCollection: ObjectMetadataInterface[],
|
||||
options: WorkspaceBuildSchemaOptions,
|
||||
isNewRelationEnabled: boolean,
|
||||
) {
|
||||
const inputTypeDefs = objectMetadataCollection
|
||||
.map((objectMetadata) => {
|
||||
@ -243,28 +219,24 @@ export class TypeDefinitionsGenerator {
|
||||
objectMetadata,
|
||||
InputTypeDefinitionKind.Create,
|
||||
options,
|
||||
isNewRelationEnabled,
|
||||
),
|
||||
// Input type for update
|
||||
this.inputTypeDefinitionFactory.create(
|
||||
optionalExtendedObjectMetadata,
|
||||
InputTypeDefinitionKind.Update,
|
||||
options,
|
||||
isNewRelationEnabled,
|
||||
),
|
||||
// Filter input type
|
||||
this.inputTypeDefinitionFactory.create(
|
||||
optionalExtendedObjectMetadata,
|
||||
InputTypeDefinitionKind.Filter,
|
||||
options,
|
||||
isNewRelationEnabled,
|
||||
),
|
||||
// OrderBy input type
|
||||
this.inputTypeDefinitionFactory.create(
|
||||
optionalExtendedObjectMetadata,
|
||||
InputTypeDefinitionKind.OrderBy,
|
||||
options,
|
||||
isNewRelationEnabled,
|
||||
),
|
||||
];
|
||||
})
|
||||
@ -300,34 +272,14 @@ export class TypeDefinitionsGenerator {
|
||||
throw new Error('Workspace ID not found');
|
||||
}
|
||||
|
||||
const isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
|
||||
FeatureFlagKey.IsNewRelationEnabled,
|
||||
workspaceId,
|
||||
const objectTypeDefs = objectMetadataCollectionWithCompositeFields.map(
|
||||
(objectMetadata) =>
|
||||
this.extendObjectTypeDefinitionV2Factory.create(
|
||||
objectMetadata,
|
||||
options,
|
||||
),
|
||||
);
|
||||
|
||||
if (!isNewRelationEnabled) {
|
||||
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);
|
||||
}
|
||||
this.typeDefinitionsStorage.addObjectTypes(objectTypeDefs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +41,6 @@ export const generateFields = <
|
||||
kind: T,
|
||||
options: WorkspaceBuildSchemaOptions,
|
||||
typeFactory: TypeFactory<T>,
|
||||
isNewRelationEnabled = false,
|
||||
): T extends InputTypeDefinitionKind
|
||||
? GraphQLInputFieldConfigMap
|
||||
: GraphQLFieldConfigMap<any, any> => {
|
||||
@ -53,8 +52,7 @@ export const generateFields = <
|
||||
fieldMetadata,
|
||||
FieldMetadataType.RELATION,
|
||||
) &&
|
||||
(fieldMetadata.settings?.relationType !== RelationType.MANY_TO_ONE ||
|
||||
!isNewRelationEnabled)
|
||||
fieldMetadata.settings?.relationType !== RelationType.MANY_TO_ONE
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -25,13 +25,11 @@ export class WorkspaceGraphQLSchemaFactory {
|
||||
objectMetadataCollection: ObjectMetadataInterface[],
|
||||
workspaceResolverBuilderMethods: WorkspaceResolverBuilderMethods,
|
||||
options: WorkspaceBuildSchemaOptions = {},
|
||||
isNewRelationEnabled = false,
|
||||
): Promise<GraphQLSchema> {
|
||||
// Generate type definitions
|
||||
await this.typeDefinitionsGenerator.generate(
|
||||
objectMetadataCollection,
|
||||
options,
|
||||
isNewRelationEnabled,
|
||||
);
|
||||
|
||||
// Generate schema
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
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 { TypeDefinitionsGenerator } from './type-definitions.generator';
|
||||
@ -12,11 +11,7 @@ import { TypeMapperService } from './services/type-mapper.service';
|
||||
import { TypeDefinitionsStorage } from './storages/type-definitions.storage';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ObjectMetadataModule,
|
||||
FeatureFlagModule,
|
||||
WorkspaceResolverBuilderModule,
|
||||
],
|
||||
imports: [ObjectMetadataModule, WorkspaceResolverBuilderModule],
|
||||
providers: [
|
||||
TypeDefinitionsStorage,
|
||||
TypeMapperService,
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { makeExecutableSchema } from '@graphql-tools/schema';
|
||||
import chalk from 'chalk';
|
||||
import { GraphQLSchema, printSchema } from 'graphql';
|
||||
import { gql } from 'graphql-tag';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface';
|
||||
|
||||
import {
|
||||
GraphqlQueryRunnerException,
|
||||
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 { 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 { 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 { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.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 { 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 { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceSchemaFactory {
|
||||
@ -43,21 +39,6 @@ export class WorkspaceSchemaFactory {
|
||||
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 =
|
||||
await this.dataSourceService.getDataSourcesMetadataFromWorkspaceId(
|
||||
authContext.workspace.id,
|
||||
@ -140,7 +121,6 @@ export class WorkspaceSchemaFactory {
|
||||
objectMetadataCollection,
|
||||
workspaceResolverBuilderMethodNames,
|
||||
{},
|
||||
isNewRelationEnabled,
|
||||
);
|
||||
|
||||
usedScalarNames =
|
||||
|
||||
@ -11,7 +11,6 @@ export class RestApiGetManyHandler extends RestApiBaseHandler {
|
||||
objectMetadataNameSingular,
|
||||
objectMetadataNamePlural,
|
||||
repository,
|
||||
dataSource,
|
||||
objectMetadata,
|
||||
objectMetadataItemWithFieldsMaps,
|
||||
} = await this.getRepositoryAndMetadataOrFail(request);
|
||||
@ -20,7 +19,6 @@ export class RestApiGetManyHandler extends RestApiBaseHandler {
|
||||
await this.findRecords({
|
||||
request,
|
||||
repository,
|
||||
dataSource,
|
||||
objectMetadata,
|
||||
objectMetadataNameSingular,
|
||||
objectMetadataItemWithFieldsMaps,
|
||||
|
||||
@ -21,7 +21,6 @@ export class RestApiGetOneHandler extends RestApiBaseHandler {
|
||||
const {
|
||||
objectMetadataNameSingular,
|
||||
repository,
|
||||
dataSource,
|
||||
objectMetadata,
|
||||
objectMetadataItemWithFieldsMaps,
|
||||
} = await this.getRepositoryAndMetadataOrFail(request);
|
||||
@ -30,7 +29,6 @@ export class RestApiGetOneHandler extends RestApiBaseHandler {
|
||||
request,
|
||||
recordId,
|
||||
repository,
|
||||
dataSource,
|
||||
objectMetadata,
|
||||
objectMetadataNameSingular,
|
||||
objectMetadataItemWithFieldsMaps,
|
||||
|
||||
@ -1,37 +1,35 @@
|
||||
import { BadRequestException, Inject } from '@nestjs/common';
|
||||
|
||||
import { Request } from 'express';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
import { In, ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import {
|
||||
ObjectRecord,
|
||||
OrderByDirection,
|
||||
} 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 { 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 { 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 {
|
||||
Depth,
|
||||
DepthInputFactory,
|
||||
MAX_DEPTH,
|
||||
} 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 { 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 { 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 { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
|
||||
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
|
||||
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 { 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 { 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 {
|
||||
hasNextPage?: boolean;
|
||||
@ -284,7 +282,6 @@ export abstract class RestApiBaseHandler {
|
||||
request,
|
||||
recordId,
|
||||
repository,
|
||||
dataSource,
|
||||
objectMetadata,
|
||||
objectMetadataNameSingular,
|
||||
objectMetadataItemWithFieldsMaps,
|
||||
@ -292,7 +289,6 @@ export abstract class RestApiBaseHandler {
|
||||
request: Request;
|
||||
recordId?: string;
|
||||
repository: WorkspaceRepository<ObjectLiteral>;
|
||||
dataSource: WorkspaceDataSource;
|
||||
objectMetadata: any;
|
||||
objectMetadataNameSingular: string;
|
||||
objectMetadataItemWithFieldsMaps:
|
||||
@ -316,7 +312,6 @@ export abstract class RestApiBaseHandler {
|
||||
fieldMetadataMapByName,
|
||||
fieldMetadataMapByJoinColumnName,
|
||||
objectMetadata.objectMetadataMaps,
|
||||
dataSource.featureFlagMap,
|
||||
);
|
||||
|
||||
const filters = this.computeFilters(inputs);
|
||||
@ -366,7 +361,6 @@ export abstract class RestApiBaseHandler {
|
||||
records,
|
||||
objectMetadataItemWithFieldsMaps as any,
|
||||
objectMetadata.objectMetadataMaps,
|
||||
dataSource.featureFlagMap[FeatureFlagKey.IsNewRelationEnabled],
|
||||
),
|
||||
totalCount,
|
||||
hasMoreRecords,
|
||||
|
||||
Reference in New Issue
Block a user