fieldmetadatatype + featurelfag creation (#13021)

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Guillim
2025-07-08 12:23:28 +02:00
committed by GitHub
parent 56607c0449
commit a5deddaffd
47 changed files with 1447 additions and 793 deletions

View File

@ -112,24 +112,29 @@ export class ExtendObjectTypeDefinitionV2Factory {
for (const fieldMetadata of objectMetadata.fields) {
// Ignore non-relation fields as they are already defined
if (
!isFieldMetadataInterfaceOfType(
const isRelation =
isFieldMetadataInterfaceOfType(
fieldMetadata,
FieldMetadataType.RELATION,
)
) {
) ||
isFieldMetadataInterfaceOfType(
fieldMetadata,
FieldMetadataType.MORPH_RELATION,
);
if (!isRelation) {
continue;
}
if (!fieldMetadata.settings) {
throw new Error(
`Field Metadata of type RELATION with id ${fieldMetadata.id} has no settings`,
`Field Metadata of type RELATION or MORPH_RELATION with id ${fieldMetadata.id} has no settings`,
);
}
if (!fieldMetadata.relationTargetObjectMetadataId) {
throw new Error(
`Field Metadata of type RELATION with id ${fieldMetadata.id} has no relation target object metadata id`,
`Field Metadata of type RELATION or MORPH_RELATION with id ${fieldMetadata.id} has no relation target object metadata id`,
);
}

View File

@ -19,17 +19,19 @@ export class RelationTypeV2Factory {
) {}
public create(
fieldMetadata: FieldMetadataInterface<FieldMetadataType.RELATION>,
fieldMetadata: FieldMetadataInterface<
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
>,
): GraphQLOutputType {
if (!fieldMetadata.settings) {
throw new Error(
`Field Metadata of type RELATION with id ${fieldMetadata.id} has no settings`,
`Field Metadata of type RELATION or MORPH_RELATION with id ${fieldMetadata.id} has no settings`,
);
}
if (!fieldMetadata.relationTargetObjectMetadataId) {
throw new Error(
`Field Metadata of type RELATION with id ${fieldMetadata.id} has no relation target object metadata id`,
`Field Metadata of type RELATION or MORPH_RELATION with id ${fieldMetadata.id} has no relation target object metadata id`,
);
}

View File

@ -15,7 +15,10 @@ import {
} from 'graphql';
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import {
FieldMetadataSettings,
NumberDataType,
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { OrderByDirectionType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/enum';
import {
@ -62,7 +65,11 @@ export class TypeMapperService {
settings?: FieldMetadataSettings<FieldMetadataType>,
isIdField?: boolean,
): GraphQLScalarType | undefined {
if (isIdField || fieldMetadataType === FieldMetadataType.RELATION) {
if (
isIdField ||
fieldMetadataType === FieldMetadataType.RELATION ||
fieldMetadataType === FieldMetadataType.MORPH_RELATION
) {
return GraphQLID;
}
const typeScalarMapping = new Map<FieldMetadataType, GraphQLScalarType>([
@ -75,7 +82,7 @@ export class TypeMapperService {
FieldMetadataType.NUMBER,
getNumberScalarType(
(settings as FieldMetadataSettings<FieldMetadataType.NUMBER>)
?.dataType,
?.dataType ?? NumberDataType.FLOAT,
),
],
[FieldMetadataType.NUMERIC, BigFloatScalarType],
@ -97,7 +104,11 @@ export class TypeMapperService {
settings?: FieldMetadataSettings<FieldMetadataType>,
isIdField?: boolean,
): GraphQLInputObjectType | GraphQLScalarType | undefined {
if (isIdField || fieldMetadataType === FieldMetadataType.RELATION) {
if (
isIdField ||
fieldMetadataType === FieldMetadataType.RELATION ||
fieldMetadataType === FieldMetadataType.MORPH_RELATION
) {
return UUIDFilterType;
}
@ -137,6 +148,7 @@ export class TypeMapperService {
const typeOrderByMapping = new Map<FieldMetadataType, GraphQLEnumType>([
[FieldMetadataType.UUID, OrderByDirectionType],
[FieldMetadataType.RELATION, OrderByDirectionType],
[FieldMetadataType.MORPH_RELATION, OrderByDirectionType],
[FieldMetadataType.TEXT, OrderByDirectionType],
[FieldMetadataType.DATE_TIME, OrderByDirectionType],
[FieldMetadataType.DATE, OrderByDirectionType],

View File

@ -64,9 +64,17 @@ export const generateFields = <
for (const fieldMetadata of objectMetadata.fields) {
let generatedField;
if (
isFieldMetadataInterfaceOfType(fieldMetadata, FieldMetadataType.RELATION)
) {
const isRelation =
isFieldMetadataInterfaceOfType(
fieldMetadata,
FieldMetadataType.RELATION,
) ||
isFieldMetadataInterfaceOfType(
fieldMetadata,
FieldMetadataType.MORPH_RELATION,
);
if (isRelation) {
generatedField = generateRelationField({
fieldMetadata,
kind,
@ -162,7 +170,9 @@ const generateRelationField = <
typeFactory,
isRelationConnectEnabled,
}: {
fieldMetadata: FieldMetadataInterface<FieldMetadataType.RELATION>;
fieldMetadata: FieldMetadataInterface<
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
>;
kind: T;
options: WorkspaceBuildSchemaOptions;
typeFactory: TypeFactory<T>;

View File

@ -130,6 +130,12 @@ describe('mapFieldMetadataToGraphqlQuery', () => {
} as FieldMetadataDefaultSettings;
}
if (fieldMetadataType === FieldMetadataType.MORPH_RELATION) {
field.settings = {
relationType: RelationType.MANY_TO_ONE,
} as FieldMetadataDefaultSettings;
}
expect(
mapFieldMetadataToGraphqlQuery(objectMetadataMapsMock, field),
).toBeDefined();

View File

@ -38,11 +38,15 @@ export const mapFieldMetadataToGraphqlQuery = (
FieldMetadataType.TS_VECTOR,
].includes(fieldType);
const isRelation =
isFieldMetadataInterfaceOfType(field, FieldMetadataType.RELATION) ||
isFieldMetadataInterfaceOfType(field, FieldMetadataType.MORPH_RELATION);
if (fieldIsSimpleValue) {
return field.name;
} else if (
maxDepthForRelations > 0 &&
isFieldMetadataInterfaceOfType(field, FieldMetadataType.RELATION) &&
isRelation &&
field.settings?.relationType === RelationType.MANY_TO_ONE
) {
const targetObjectMetadataId = field.relationTargetObjectMetadataId;
@ -69,7 +73,7 @@ export const mapFieldMetadataToGraphqlQuery = (
}`;
} else if (
maxDepthForRelations > 0 &&
isFieldMetadataInterfaceOfType(field, FieldMetadataType.RELATION) &&
isRelation &&
field.settings?.relationType === RelationType.ONE_TO_MANY
) {
const targetObjectMetadataId = field.relationTargetObjectMetadataId;