Deprecate object metadata maps in favor of flat entities (#16080)
## Context Deprecating the old objectMetadataMap type in favour of split flat entities to match with our new caching. In the long run, trying to achieve: - Better performance through caching - Consistent data access patterns across the codebase - Reduced database queries Now that everything is based on flat entities, which are cached, we can finish the refactoring of workspace context cache which should already improve performances. Then the last step will be to consume that new cache in the new global datasource to get rid of the many workspace datasources stored in the server
This commit is contained in:
+10
-7
@@ -9,9 +9,9 @@ import {
|
||||
type FieldMetadataComplexOption,
|
||||
type FieldMetadataDefaultOption,
|
||||
} from 'src/engine/metadata-modules/field-metadata/dtos/options.input';
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { isEnumFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { transformEnumValue } from 'src/engine/utils/transform-enum-value';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@@ -23,25 +23,28 @@ export class EnumFieldMetadataGqlEnumTypeGenerator {
|
||||
|
||||
constructor(private readonly gqlTypesStorage: GqlTypesStorage) {}
|
||||
|
||||
public buildAndStore(objectMetadata: ObjectMetadataEntity) {
|
||||
for (const fieldMetadata of objectMetadata.fields) {
|
||||
public buildAndStore(
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
fields: FlatFieldMetadata[],
|
||||
) {
|
||||
for (const fieldMetadata of fields) {
|
||||
if (!isEnumFieldMetadataType(fieldMetadata.type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.gqlTypesStorage.addGqlType(
|
||||
computeEnumFieldGqlTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
fieldMetadata.name,
|
||||
),
|
||||
this.generateEnum(objectMetadata.nameSingular, fieldMetadata),
|
||||
this.generateEnum(flatObjectMetadata.nameSingular, fieldMetadata),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private generateEnum(
|
||||
objectName: string,
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
): GraphQLEnumType {
|
||||
// FixMe: It's a hack until Typescript get fixed on union types for reduce function
|
||||
// https://github.com/microsoft/TypeScript/issues/36390
|
||||
|
||||
+60
-27
@@ -4,6 +4,7 @@ import {
|
||||
type CompositeType,
|
||||
compositeTypeDefinitions,
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { CompositeFieldMetadataGqlEnumTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/enum-types/composite-field-metadata-gql-enum-type.generator';
|
||||
import { EnumFieldMetadataGqlEnumTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/enum-types/enum-field-metadata-gql-enum-type.generator';
|
||||
@@ -19,9 +20,10 @@ import { ObjectMetadataGqlObjectTypeGenerator } from 'src/engine/api/graphql/wor
|
||||
import { ObjectMetadataWithRelationsGqlObjectTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/object-types/object-metadata-with-relations-gql-object-type.generator';
|
||||
import { MutationTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/root-types/mutation-type.generator';
|
||||
import { QueryTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/root-types/query-type.generator';
|
||||
import { objectContainsMorphRelationField } from 'src/engine/api/graphql/workspace-schema-builder/utils/object-contains-morph-relation-field.util';
|
||||
import { objectContainsRelationField } from 'src/engine/api/graphql/workspace-schema-builder/utils/object-contains-relation-field';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
import { getFlatFieldsFromFlatObjectMetadata } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-flat-fields-for-flat-object-metadata.util';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFieldMetadataType } from 'src/engine/utils/is-morph-or-relation-field-metadata-type.util';
|
||||
|
||||
@Injectable()
|
||||
export class GqlTypeGenerator {
|
||||
@@ -44,14 +46,14 @@ export class GqlTypeGenerator {
|
||||
private readonly mutationTypeGenerator: MutationTypeGenerator,
|
||||
) {}
|
||||
|
||||
async buildAndStore(objectMetadataCollection: ObjectMetadataEntity[]) {
|
||||
async buildAndStore(context: SchemaGenerationContext) {
|
||||
const compositeTypeCollection = [...compositeTypeDefinitions.values()];
|
||||
|
||||
this.buildAndStoreCompositeFieldMetadataGqlTypes(compositeTypeCollection);
|
||||
this.buildAndStoreDateFieldMetadataGroupByGqlTypes();
|
||||
this.buildAndStoreObjectMetadataGqlTypes(objectMetadataCollection);
|
||||
await this.queryTypeGenerator.buildAndStore(objectMetadataCollection);
|
||||
this.mutationTypeGenerator.buildAndStore(objectMetadataCollection);
|
||||
this.buildAndStoreObjectMetadataGqlTypes(context);
|
||||
await this.queryTypeGenerator.buildAndStore(context);
|
||||
this.mutationTypeGenerator.buildAndStore(context);
|
||||
}
|
||||
|
||||
private buildAndStoreCompositeFieldMetadataGqlTypes(
|
||||
@@ -75,36 +77,67 @@ export class GqlTypeGenerator {
|
||||
}
|
||||
|
||||
private buildAndStoreObjectMetadataGqlTypes(
|
||||
dynamicObjectMetadataCollection: ObjectMetadataEntity[],
|
||||
context: SchemaGenerationContext,
|
||||
) {
|
||||
const { flatObjectMetadataMaps, flatFieldMetadataMaps } = context;
|
||||
const objectMetadataCollection = Object.values(
|
||||
flatObjectMetadataMaps.byId,
|
||||
).filter(isDefined);
|
||||
|
||||
this.logger.log(
|
||||
`Generating metadata objects: [${dynamicObjectMetadataCollection
|
||||
`Generating metadata objects: [${objectMetadataCollection
|
||||
.map((object) => object.nameSingular)
|
||||
.join(', ')}]`,
|
||||
);
|
||||
|
||||
for (const objectMetadata of dynamicObjectMetadataCollection) {
|
||||
this.enumFieldMetadataGqlEnumTypeGenerator.buildAndStore(objectMetadata);
|
||||
this.objectMetadataGqlObjectTypeGenerator.buildAndStore(objectMetadata);
|
||||
this.edgeGqlObjectTypeGenerator.buildAndStore(objectMetadata);
|
||||
this.connectionGqlObjectTypeGenerator.buildAndStore(objectMetadata);
|
||||
this.groupByConnectionGqlObjectTypeGenerator.buildAndStore(
|
||||
objectMetadata,
|
||||
);
|
||||
this.relationConnectGqlInputTypeGenerator.buildAndStore(objectMetadata);
|
||||
this.objectMetadataGqlInputTypeGenerator.buildAndStore(
|
||||
objectMetadata,
|
||||
dynamicObjectMetadataCollection,
|
||||
for (const flatObjectMetadata of objectMetadataCollection) {
|
||||
const fields = getFlatFieldsFromFlatObjectMetadata(
|
||||
flatObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
if (
|
||||
objectContainsRelationField(objectMetadata) ||
|
||||
objectContainsMorphRelationField(objectMetadata)
|
||||
)
|
||||
this.enumFieldMetadataGqlEnumTypeGenerator.buildAndStore(
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
);
|
||||
this.objectMetadataGqlObjectTypeGenerator.buildAndStore(
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
);
|
||||
this.edgeGqlObjectTypeGenerator.buildAndStore(flatObjectMetadata);
|
||||
this.connectionGqlObjectTypeGenerator.buildAndStore(
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
);
|
||||
this.groupByConnectionGqlObjectTypeGenerator.buildAndStore(
|
||||
flatObjectMetadata,
|
||||
);
|
||||
this.relationConnectGqlInputTypeGenerator.buildAndStore(
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
context,
|
||||
);
|
||||
this.objectMetadataGqlInputTypeGenerator.buildAndStore(
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
context,
|
||||
);
|
||||
|
||||
if (this.objectContainsRelationOrMorphField(fields)) {
|
||||
this.objectMetadataWithRelationsGqlObjectTypeGenerator.buildAndStore(
|
||||
objectMetadata,
|
||||
dynamicObjectMetadataCollection,
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
context,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private objectContainsRelationOrMorphField(
|
||||
fields: FlatFieldMetadata[],
|
||||
): boolean {
|
||||
return fields.some((field) =>
|
||||
isMorphOrRelationFieldMetadataType(field.type),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+28
-19
@@ -16,15 +16,16 @@ import {
|
||||
TypeOptions,
|
||||
} from 'src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
import { computeFieldInputTypeOptions } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-field-input-type-options.util';
|
||||
import { computeCompositeFieldInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-composite-field-input-type-key.util';
|
||||
import { computeEnumFieldGqlTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-enum-field-gql-type-key.util';
|
||||
import { computeObjectMetadataInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-input-type.util';
|
||||
import { isFieldMetadataRelationOrMorphRelation } from 'src/engine/api/graphql/workspace-schema-builder/utils/is-field-metadata-relation-or-morph-relation.utils';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { isEnumFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@Injectable()
|
||||
@@ -38,15 +39,20 @@ export class ObjectMetadataCreateGqlInputTypeGenerator {
|
||||
private readonly typeMapperService: TypeMapperService,
|
||||
) {}
|
||||
|
||||
public buildAndStore(objectMetadata: ObjectMetadataEntity) {
|
||||
public buildAndStore(
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
fields: FlatFieldMetadata[],
|
||||
_context: SchemaGenerationContext,
|
||||
) {
|
||||
const inputType = new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.Create.toString()}Input`,
|
||||
description: objectMetadata.description,
|
||||
fields: () => this.generateFields(objectMetadata),
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.Create.toString()}Input`,
|
||||
description: flatObjectMetadata.description,
|
||||
fields: () =>
|
||||
this.generateFields(flatObjectMetadata.nameSingular, fields),
|
||||
}) as GraphQLInputObjectType;
|
||||
|
||||
const key = computeObjectMetadataInputTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
GqlInputTypeDefinitionKind.Create,
|
||||
);
|
||||
|
||||
@@ -54,11 +60,12 @@ export class ObjectMetadataCreateGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectNameSingular: string,
|
||||
fields: FlatFieldMetadata[],
|
||||
): GraphQLInputFieldConfigMap {
|
||||
const allGeneratedFields: GraphQLInputFieldConfigMap = {};
|
||||
|
||||
for (const fieldMetadata of objectMetadata.fields) {
|
||||
for (const fieldMetadata of fields) {
|
||||
const typeOptions = computeFieldInputTypeOptions(
|
||||
fieldMetadata,
|
||||
GqlInputTypeDefinitionKind.Create,
|
||||
@@ -66,24 +73,26 @@ export class ObjectMetadataCreateGqlInputTypeGenerator {
|
||||
|
||||
let generatedFields;
|
||||
|
||||
if (isFieldMetadataRelationOrMorphRelation(fieldMetadata)) {
|
||||
if (isMorphOrRelationFlatFieldMetadata(fieldMetadata)) {
|
||||
const relationFieldMetadata = fieldMetadata;
|
||||
|
||||
generatedFields = {
|
||||
...this.relationFieldMetadataGqlInputTypeGenerator.generateSimpleRelationFieldCreateOrUpdateInputType(
|
||||
{
|
||||
fieldMetadata,
|
||||
fieldMetadata: relationFieldMetadata,
|
||||
typeOptions,
|
||||
},
|
||||
),
|
||||
...this.relationFieldMetadataGqlInputTypeGenerator.generateConnectRelationFieldInputType(
|
||||
{
|
||||
fieldMetadata,
|
||||
fieldMetadata: relationFieldMetadata,
|
||||
typeOptions,
|
||||
},
|
||||
),
|
||||
};
|
||||
} else if (isEnumFieldMetadataType(fieldMetadata.type)) {
|
||||
generatedFields = this.generateEnumFieldCreateInputType(
|
||||
objectMetadata,
|
||||
objectNameSingular,
|
||||
fieldMetadata,
|
||||
typeOptions,
|
||||
);
|
||||
@@ -106,12 +115,12 @@ export class ObjectMetadataCreateGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateEnumFieldCreateInputType(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
objectNameSingular: string,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
typeOptions: TypeOptions,
|
||||
) {
|
||||
const key = computeEnumFieldGqlTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
objectNameSingular,
|
||||
fieldMetadata.name,
|
||||
);
|
||||
|
||||
@@ -141,7 +150,7 @@ export class ObjectMetadataCreateGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateCompositeFieldCreateInputType(
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
typeOptions: TypeOptions,
|
||||
) {
|
||||
const key = computeCompositeFieldInputTypeKey(
|
||||
@@ -175,7 +184,7 @@ export class ObjectMetadataCreateGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateAtomicFieldCreateInputType(
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
typeOptions: TypeOptions,
|
||||
) {
|
||||
const type = this.typeMapperService.mapToScalarType(
|
||||
|
||||
+27
-19
@@ -21,11 +21,11 @@ import { computeCompositeFieldInputTypeKey } from 'src/engine/api/graphql/worksp
|
||||
import { computeEnumFieldGqlTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-enum-field-gql-type-key.util';
|
||||
import { computeObjectMetadataInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-input-type.util';
|
||||
import { createGqlEnumFilterType } from 'src/engine/api/graphql/workspace-schema-builder/utils/create-gql-enum-filter-type.util';
|
||||
import { isFieldMetadataRelationOrMorphRelation } from 'src/engine/api/graphql/workspace-schema-builder/utils/is-field-metadata-relation-or-morph-relation.utils';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { isEnumFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@Injectable()
|
||||
@@ -39,15 +39,19 @@ export class ObjectMetadataFilterGqlInputTypeGenerator {
|
||||
private readonly typeMapperService: TypeMapperService,
|
||||
) {}
|
||||
|
||||
public buildAndStore(objectMetadata: ObjectMetadataEntity) {
|
||||
public buildAndStore(
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
fields: FlatFieldMetadata[],
|
||||
) {
|
||||
const inputType = new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.Filter.toString()}Input`,
|
||||
description: objectMetadata.description,
|
||||
fields: () => this.generateFields(objectMetadata, inputType),
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.Filter.toString()}Input`,
|
||||
description: flatObjectMetadata.description,
|
||||
fields: () =>
|
||||
this.generateFields(flatObjectMetadata.nameSingular, fields, inputType),
|
||||
}) as GraphQLInputObjectType;
|
||||
|
||||
const key = computeObjectMetadataInputTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
GqlInputTypeDefinitionKind.Filter,
|
||||
);
|
||||
|
||||
@@ -55,7 +59,8 @@ export class ObjectMetadataFilterGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectNameSingular: string,
|
||||
fields: FlatFieldMetadata[],
|
||||
inputType: GraphQLInputObjectType,
|
||||
): GraphQLInputFieldConfigMap {
|
||||
const andOrType = this.typeMapperService.applyTypeOptions(inputType, {
|
||||
@@ -65,17 +70,20 @@ export class ObjectMetadataFilterGqlInputTypeGenerator {
|
||||
});
|
||||
const allGeneratedFields: GraphQLInputFieldConfigMap = {};
|
||||
|
||||
for (const fieldMetadata of objectMetadata.fields) {
|
||||
fieldMetadata.isNullable = true;
|
||||
for (const fieldMetadata of fields) {
|
||||
const modifiedFieldMetadata = {
|
||||
...fieldMetadata,
|
||||
isNullable: true,
|
||||
};
|
||||
|
||||
const typeOptions = computeFieldInputTypeOptions(
|
||||
fieldMetadata,
|
||||
modifiedFieldMetadata,
|
||||
GqlInputTypeDefinitionKind.Filter,
|
||||
);
|
||||
|
||||
let generatedFields;
|
||||
|
||||
if (isFieldMetadataRelationOrMorphRelation(fieldMetadata)) {
|
||||
if (isMorphOrRelationFlatFieldMetadata(fieldMetadata)) {
|
||||
generatedFields =
|
||||
this.relationFieldMetadataGqlInputTypeGenerator.generateSimpleRelationFieldFilterInputType(
|
||||
{
|
||||
@@ -85,7 +93,7 @@ export class ObjectMetadataFilterGqlInputTypeGenerator {
|
||||
);
|
||||
} else if (isEnumFieldMetadataType(fieldMetadata.type)) {
|
||||
generatedFields = this.generateEnumFieldFilterInputType(
|
||||
objectMetadata,
|
||||
objectNameSingular,
|
||||
fieldMetadata,
|
||||
typeOptions,
|
||||
);
|
||||
@@ -120,12 +128,12 @@ export class ObjectMetadataFilterGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateEnumFieldFilterInputType(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
objectNameSingular: string,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
typeOptions: TypeOptions,
|
||||
) {
|
||||
const key = computeEnumFieldGqlTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
objectNameSingular,
|
||||
fieldMetadata.name,
|
||||
);
|
||||
|
||||
@@ -152,7 +160,7 @@ export class ObjectMetadataFilterGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateCompositeFieldFilterInputType(
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
typeOptions: TypeOptions,
|
||||
) {
|
||||
const key = computeCompositeFieldInputTypeKey(
|
||||
@@ -181,7 +189,7 @@ export class ObjectMetadataFilterGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateAtomicFieldFilterInputType(
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
typeOptions: TypeOptions,
|
||||
) {
|
||||
const type = this.typeMapperService.mapToFilterType(
|
||||
|
||||
+18
-28
@@ -16,14 +16,13 @@ import { GROUP_BY_DATE_GRANULARITY_INPUT_KEY } from 'src/engine/api/graphql/work
|
||||
import { RelationFieldMetadataGqlInputTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/input-types/relation-field-metadata-gql-type.generator';
|
||||
import { TypeMapperService } from 'src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
import { computeCompositeFieldInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-composite-field-input-type-key.util';
|
||||
import { computeObjectMetadataInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-input-type.util';
|
||||
import { isFieldMetadataRelationOrMorphRelation } from 'src/engine/api/graphql/workspace-schema-builder/utils/is-field-metadata-relation-or-morph-relation.utils';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
||||
import { generateObjectMetadataMaps } from 'src/engine/metadata-modules/utils/generate-object-metadata-maps.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@Injectable()
|
||||
@@ -31,8 +30,6 @@ export class ObjectMetadataGroupByGqlInputTypeGenerator {
|
||||
private readonly logger = new Logger(
|
||||
ObjectMetadataGroupByGqlInputTypeGenerator.name,
|
||||
);
|
||||
private objectMetadataCollection: ObjectMetadataEntity[] = [];
|
||||
private objectMetadataMaps: ObjectMetadataMaps | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly gqlTypesStorage: GqlTypesStorage,
|
||||
@@ -41,24 +38,18 @@ export class ObjectMetadataGroupByGqlInputTypeGenerator {
|
||||
) {}
|
||||
|
||||
public buildAndStore(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectMetadataCollection?: ObjectMetadataEntity[],
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
fields: FlatFieldMetadata[],
|
||||
context: SchemaGenerationContext,
|
||||
) {
|
||||
if (isDefined(objectMetadataCollection)) {
|
||||
this.objectMetadataCollection = objectMetadataCollection;
|
||||
this.objectMetadataMaps = generateObjectMetadataMaps(
|
||||
objectMetadataCollection,
|
||||
);
|
||||
}
|
||||
|
||||
const inputType = new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.GroupBy.toString()}Input`,
|
||||
description: objectMetadata.description,
|
||||
fields: () => this.generateFields(objectMetadata),
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.GroupBy.toString()}Input`,
|
||||
description: flatObjectMetadata.description,
|
||||
fields: () => this.generateFields(fields, context),
|
||||
}) as GraphQLInputObjectType;
|
||||
|
||||
const key = computeObjectMetadataInputTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
GqlInputTypeDefinitionKind.GroupBy,
|
||||
);
|
||||
|
||||
@@ -66,17 +57,16 @@ export class ObjectMetadataGroupByGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
fields: FlatFieldMetadata[],
|
||||
context: SchemaGenerationContext,
|
||||
): GraphQLInputFieldConfigMap {
|
||||
const allGeneratedFields: GraphQLInputFieldConfigMap = {};
|
||||
|
||||
for (const fieldMetadata of objectMetadata.fields) {
|
||||
const generatedField = isFieldMetadataRelationOrMorphRelation(
|
||||
fieldMetadata,
|
||||
)
|
||||
for (const fieldMetadata of fields) {
|
||||
const generatedField = isMorphOrRelationFlatFieldMetadata(fieldMetadata)
|
||||
? this.relationFieldMetadataGqlInputTypeGenerator.generateSimpleRelationFieldGroupByInputType(
|
||||
fieldMetadata,
|
||||
this.objectMetadataMaps,
|
||||
context,
|
||||
)
|
||||
: this.generateField(fieldMetadata);
|
||||
|
||||
@@ -86,7 +76,7 @@ export class ObjectMetadataGroupByGqlInputTypeGenerator {
|
||||
return allGeneratedFields;
|
||||
}
|
||||
|
||||
private generateField(fieldMetadata: FieldMetadataEntity) {
|
||||
private generateField(fieldMetadata: FlatFieldMetadata) {
|
||||
if (isCompositeFieldMetadataType(fieldMetadata.type))
|
||||
return this.generateCompositeFieldGroupByInputType(fieldMetadata);
|
||||
|
||||
@@ -124,7 +114,7 @@ export class ObjectMetadataGroupByGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateCompositeFieldGroupByInputType(
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
) {
|
||||
const key = computeCompositeFieldInputTypeKey(
|
||||
fieldMetadata.type,
|
||||
|
||||
+22
-11
@@ -6,7 +6,9 @@ import { ObjectMetadataGroupByGqlInputTypeGenerator } from 'src/engine/api/graph
|
||||
import { ObjectMetadataOrderByGqlInputTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/input-types/order-by-input/object-metadata-order-by-gql-input-type.generator';
|
||||
import { ObjectMetadataOrderByWithGroupByGqlInputTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/input-types/order-by-input/object-metadata-order-by-with-group-by-gql-input-type.generator';
|
||||
import { ObjectMetadataUpdateGqlInputTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/input-types/update-input/object-metadata-update-gql-input-type.generator';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
|
||||
@Injectable()
|
||||
export class ObjectMetadataGqlInputTypeGenerator {
|
||||
@@ -20,28 +22,37 @@ export class ObjectMetadataGqlInputTypeGenerator {
|
||||
) {}
|
||||
|
||||
public buildAndStore(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectMetadataCollection?: ObjectMetadataEntity[],
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
fields: FlatFieldMetadata[],
|
||||
context: SchemaGenerationContext,
|
||||
) {
|
||||
this.objectMetadataCreateGqlInputTypeGenerator.buildAndStore(
|
||||
objectMetadata,
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
context,
|
||||
);
|
||||
this.objectMetadataUpdateGqlInputTypeGenerator.buildAndStore(
|
||||
objectMetadata,
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
context,
|
||||
);
|
||||
this.objectMetadataFilterGqlInputTypeGenerator.buildAndStore(
|
||||
objectMetadata,
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
);
|
||||
this.objectMetadataOrderByGqlInputTypeGenerator.buildAndStore({
|
||||
objectMetadata,
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
});
|
||||
this.objectMetadataOrderByWithGroupByGqlInputTypeGenerator.buildAndStore({
|
||||
objectMetadata,
|
||||
objectMetadataCollection,
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
context,
|
||||
});
|
||||
this.objectMetadataGroupByGqlInputTypeGenerator.buildAndStore(
|
||||
objectMetadata,
|
||||
objectMetadataCollection,
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
context,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+17
-15
@@ -12,13 +12,12 @@ import {
|
||||
TypeOptions,
|
||||
} from 'src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
import { computeFieldInputTypeOptions } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-field-input-type-options.util';
|
||||
import { computeCompositeFieldInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-composite-field-input-type-key.util';
|
||||
import { isFieldMetadataRelationOrMorphRelation } from 'src/engine/api/graphql/workspace-schema-builder/utils/is-field-metadata-relation-or-morph-relation.utils';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
|
||||
@Injectable()
|
||||
export class ObjectMetadataOrderByBaseGenerator {
|
||||
@@ -29,35 +28,38 @@ export class ObjectMetadataOrderByBaseGenerator {
|
||||
) {}
|
||||
|
||||
public generateFields({
|
||||
objectMetadata,
|
||||
fields,
|
||||
logger,
|
||||
orderByDateGranularity,
|
||||
objectMetadataMaps,
|
||||
context,
|
||||
}: {
|
||||
objectMetadata: ObjectMetadataEntity;
|
||||
fields: FlatFieldMetadata[];
|
||||
logger: Logger;
|
||||
orderByDateGranularity?: boolean;
|
||||
objectMetadataMaps?: ObjectMetadataMaps;
|
||||
context?: SchemaGenerationContext;
|
||||
}): GraphQLInputFieldConfigMap {
|
||||
const allGeneratedFields: GraphQLInputFieldConfigMap = {};
|
||||
|
||||
for (const fieldMetadata of objectMetadata.fields) {
|
||||
fieldMetadata.isNullable = true;
|
||||
for (const fieldMetadata of fields) {
|
||||
const modifiedFieldMetadata = {
|
||||
...fieldMetadata,
|
||||
isNullable: true,
|
||||
};
|
||||
|
||||
const typeOptions = computeFieldInputTypeOptions(
|
||||
fieldMetadata,
|
||||
modifiedFieldMetadata,
|
||||
GqlInputTypeDefinitionKind.OrderBy,
|
||||
);
|
||||
|
||||
let generatedFields;
|
||||
|
||||
if (isFieldMetadataRelationOrMorphRelation(fieldMetadata)) {
|
||||
if (isMorphOrRelationFlatFieldMetadata(fieldMetadata)) {
|
||||
generatedFields =
|
||||
this.relationFieldMetadataGqlInputTypeGenerator.generateSimpleRelationFieldOrderByInputType(
|
||||
{
|
||||
fieldMetadata,
|
||||
typeOptions,
|
||||
objectMetadataMaps,
|
||||
context,
|
||||
},
|
||||
);
|
||||
} else if (isCompositeFieldMetadataType(fieldMetadata.type)) {
|
||||
@@ -82,7 +84,7 @@ export class ObjectMetadataOrderByBaseGenerator {
|
||||
}
|
||||
|
||||
private generateCompositeFieldOrderByInputType(
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
typeOptions: TypeOptions,
|
||||
logger: Logger,
|
||||
) {
|
||||
@@ -117,7 +119,7 @@ export class ObjectMetadataOrderByBaseGenerator {
|
||||
logger,
|
||||
orderByDateGranularity,
|
||||
}: {
|
||||
fieldMetadata: FieldMetadataEntity;
|
||||
fieldMetadata: FlatFieldMetadata;
|
||||
typeOptions: TypeOptions;
|
||||
logger: Logger;
|
||||
orderByDateGranularity?: boolean;
|
||||
|
||||
+10
-7
@@ -6,7 +6,8 @@ import { GqlInputTypeDefinitionKind } from 'src/engine/api/graphql/workspace-sch
|
||||
import { ObjectMetadataOrderByBaseGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/input-types/order-by-input/object-metadata-order-by-base.generator';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { computeObjectMetadataInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-input-type.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@Injectable()
|
||||
@@ -20,22 +21,24 @@ export class ObjectMetadataOrderByGqlInputTypeGenerator {
|
||||
) {}
|
||||
|
||||
public buildAndStore({
|
||||
objectMetadata,
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
}: {
|
||||
objectMetadata: ObjectMetadataEntity;
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
fields: FlatFieldMetadata[];
|
||||
}) {
|
||||
const inputType = new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.OrderBy.toString()}Input`,
|
||||
description: objectMetadata.description,
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.OrderBy.toString()}Input`,
|
||||
description: flatObjectMetadata.description,
|
||||
fields: () =>
|
||||
this.objectMetadataOrderByBaseGenerator.generateFields({
|
||||
objectMetadata,
|
||||
fields,
|
||||
logger: this.logger,
|
||||
}),
|
||||
}) as GraphQLInputObjectType;
|
||||
|
||||
const key = computeObjectMetadataInputTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
GqlInputTypeDefinitionKind.OrderBy,
|
||||
);
|
||||
|
||||
|
||||
+43
-37
@@ -15,16 +15,15 @@ import {
|
||||
TypeOptions,
|
||||
} from 'src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
import { computeFieldInputTypeOptions } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-field-input-type-options.util';
|
||||
import { computeCompositeFieldInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-composite-field-input-type-key.util';
|
||||
import { computeObjectMetadataInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-input-type.util';
|
||||
import { getAvailableAggregationsFromObjectFields } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-available-aggregations-from-object-fields.util';
|
||||
import { isFieldMetadataRelationOrMorphRelation } from 'src/engine/api/graphql/workspace-schema-builder/utils/is-field-metadata-relation-or-morph-relation.utils';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
||||
import { generateObjectMetadataMaps } from 'src/engine/metadata-modules/utils/generate-object-metadata-maps.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@Injectable()
|
||||
@@ -39,29 +38,24 @@ export class ObjectMetadataOrderByWithGroupByGqlInputTypeGenerator {
|
||||
private readonly typeMapperService: TypeMapperService,
|
||||
) {}
|
||||
|
||||
private objectMetadataMaps?: ObjectMetadataMaps;
|
||||
|
||||
public buildAndStore({
|
||||
objectMetadata,
|
||||
objectMetadataCollection,
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
context,
|
||||
}: {
|
||||
objectMetadata: ObjectMetadataEntity;
|
||||
objectMetadataCollection?: ObjectMetadataEntity[];
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
fields: FlatFieldMetadata[];
|
||||
context: SchemaGenerationContext;
|
||||
}) {
|
||||
if (isDefined(objectMetadataCollection)) {
|
||||
this.objectMetadataMaps = generateObjectMetadataMaps(
|
||||
objectMetadataCollection,
|
||||
);
|
||||
}
|
||||
|
||||
const inputType = new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.OrderByWithGroupBy.toString()}Input`,
|
||||
description: objectMetadata.description,
|
||||
fields: () => this.generateFields(objectMetadata),
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.OrderByWithGroupBy.toString()}Input`,
|
||||
description: flatObjectMetadata.description,
|
||||
fields: () =>
|
||||
this.generateFields(flatObjectMetadata.nameSingular, fields, context),
|
||||
}) as GraphQLInputObjectType;
|
||||
|
||||
const key = computeObjectMetadataInputTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
GqlInputTypeDefinitionKind.OrderByWithGroupBy,
|
||||
);
|
||||
|
||||
@@ -69,36 +63,47 @@ export class ObjectMetadataOrderByWithGroupByGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectNameSingular: string,
|
||||
fields: FlatFieldMetadata[],
|
||||
context: SchemaGenerationContext,
|
||||
): GraphQLInputFieldConfigMap {
|
||||
return {
|
||||
...this.generateOrderByOnAggregateFields(objectMetadata),
|
||||
...this.generateOrderByOnDimensionValuesFields(objectMetadata),
|
||||
...this.generateOrderByOnAggregateFields(
|
||||
objectNameSingular,
|
||||
fields,
|
||||
context,
|
||||
),
|
||||
...this.generateOrderByOnDimensionValuesFields(fields, context),
|
||||
};
|
||||
}
|
||||
|
||||
private generateOrderByOnAggregateFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectNameSingular: string,
|
||||
fields: FlatFieldMetadata[],
|
||||
context: SchemaGenerationContext,
|
||||
): GraphQLInputFieldConfigMap {
|
||||
const allAggregatedFields: GraphQLInputFieldConfigMap = {};
|
||||
|
||||
for (const fieldMetadata of objectMetadata.fields) {
|
||||
fieldMetadata.isNullable = true;
|
||||
for (const fieldMetadata of fields) {
|
||||
const modifiedFieldMetadata = {
|
||||
...fieldMetadata,
|
||||
isNullable: true,
|
||||
};
|
||||
|
||||
const typeOptions = computeFieldInputTypeOptions(
|
||||
fieldMetadata,
|
||||
modifiedFieldMetadata,
|
||||
GqlInputTypeDefinitionKind.OrderBy,
|
||||
);
|
||||
|
||||
let generatedFields;
|
||||
|
||||
if (isFieldMetadataRelationOrMorphRelation(fieldMetadata)) {
|
||||
if (isMorphOrRelationFlatFieldMetadata(fieldMetadata)) {
|
||||
generatedFields =
|
||||
this.relationFieldMetadataGqlInputTypeGenerator.generateSimpleRelationFieldOrderByInputType(
|
||||
{
|
||||
fieldMetadata,
|
||||
typeOptions,
|
||||
objectMetadataMaps: this.objectMetadataMaps,
|
||||
context,
|
||||
},
|
||||
);
|
||||
} else if (isCompositeFieldMetadataType(fieldMetadata.type)) {
|
||||
@@ -117,7 +122,7 @@ export class ObjectMetadataOrderByWithGroupByGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
const aggregateInputType = new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.OrderByWithGroupBy.toString()}AggregateInput`,
|
||||
name: `${pascalCase(objectNameSingular)}${GqlInputTypeDefinitionKind.OrderByWithGroupBy.toString()}AggregateInput`,
|
||||
description: 'Aggregate-based ordering',
|
||||
fields: () => allAggregatedFields,
|
||||
}) as GraphQLInputObjectType;
|
||||
@@ -131,18 +136,19 @@ export class ObjectMetadataOrderByWithGroupByGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateOrderByOnDimensionValuesFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
fields: FlatFieldMetadata[],
|
||||
context: SchemaGenerationContext,
|
||||
) {
|
||||
return this.objectMetadataOrderByBaseGenerator.generateFields({
|
||||
objectMetadata,
|
||||
fields,
|
||||
logger: this.logger,
|
||||
orderByDateGranularity: true,
|
||||
objectMetadataMaps: this.objectMetadataMaps,
|
||||
context,
|
||||
});
|
||||
}
|
||||
|
||||
private generateCompositeFieldOrderByInputType(
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
typeOptions: TypeOptions,
|
||||
) {
|
||||
const key = computeCompositeFieldInputTypeKey(
|
||||
@@ -169,7 +175,7 @@ export class ObjectMetadataOrderByWithGroupByGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateAtomicFieldOrderByInputType(
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
typeOptions: TypeOptions,
|
||||
) {
|
||||
const orderByType = this.typeMapperService.mapToOrderByType(
|
||||
@@ -193,7 +199,7 @@ export class ObjectMetadataOrderByWithGroupByGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateAggregateFieldOrderByInputType(
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
) {
|
||||
const aggregations = getAvailableAggregationsFromObjectFields([
|
||||
fieldMetadata,
|
||||
|
||||
+59
-26
@@ -8,15 +8,16 @@ import {
|
||||
GraphQLString,
|
||||
} from 'graphql';
|
||||
import { RELATION_NESTED_QUERY_KEYWORDS } from 'twenty-shared/constants';
|
||||
import { getUniqueConstraintsFields } from 'twenty-shared/utils';
|
||||
import { compositeTypeDefinitions } from 'twenty-shared/types';
|
||||
import { getUniqueConstraintsFields, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { TypeMapperService } from 'src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
import { computeRelationConnectInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-relation-connect-input-type-key.util';
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@Injectable()
|
||||
@@ -26,44 +27,76 @@ export class RelationConnectGqlInputTypeGenerator {
|
||||
private readonly gqlTypesStorage: GqlTypesStorage,
|
||||
) {}
|
||||
|
||||
public buildAndStore(objectMetadata: ObjectMetadataEntity) {
|
||||
const relationConnectGqlInputType =
|
||||
this.generateRelationConnectInputType(objectMetadata);
|
||||
const key = computeRelationConnectInputTypeKey(objectMetadata.id);
|
||||
public buildAndStore(
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
fields: FlatFieldMetadata[],
|
||||
context: SchemaGenerationContext,
|
||||
) {
|
||||
const relationConnectGqlInputType = this.generateRelationConnectInputType(
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
context,
|
||||
);
|
||||
const key = computeRelationConnectInputTypeKey(flatObjectMetadata.id);
|
||||
|
||||
this.gqlTypesStorage.addGqlType(key, relationConnectGqlInputType);
|
||||
}
|
||||
|
||||
private generateRelationConnectInputType(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
fields: FlatFieldMetadata[],
|
||||
context: SchemaGenerationContext,
|
||||
): GraphQLInputObjectType {
|
||||
return new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}RelationInput`,
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}RelationInput`,
|
||||
fields: () => ({
|
||||
[RELATION_NESTED_QUERY_KEYWORDS.CONNECT]: {
|
||||
type: new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}ConnectInput`,
|
||||
fields: this.generateRelationWhereInputType(objectMetadata),
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}ConnectInput`,
|
||||
fields: this.generateRelationWhereInputType(
|
||||
flatObjectMetadata,
|
||||
fields,
|
||||
context,
|
||||
),
|
||||
}),
|
||||
description: `Connect to a ${objectMetadata.nameSingular} record`,
|
||||
description: `Connect to a ${flatObjectMetadata.nameSingular} record`,
|
||||
},
|
||||
[RELATION_NESTED_QUERY_KEYWORDS.DISCONNECT]: {
|
||||
type: GraphQLBoolean,
|
||||
description: `Disconnect from a ${objectMetadata.nameSingular} record`,
|
||||
description: `Disconnect from a ${flatObjectMetadata.nameSingular} record`,
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
private generateRelationWhereInputType(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
fields: FlatFieldMetadata[],
|
||||
context: SchemaGenerationContext,
|
||||
): Record<string, GraphQLInputFieldConfig> {
|
||||
const uniqueConstraints = getUniqueConstraintsFields<
|
||||
FieldMetadataEntity,
|
||||
ObjectMetadataEntity
|
||||
>(objectMetadata);
|
||||
const { flatIndexMaps } = context;
|
||||
|
||||
const fields: Record<
|
||||
const indexMetadatas = flatObjectMetadata.indexMetadataIds
|
||||
.map((indexId) => flatIndexMaps.byId[indexId])
|
||||
.filter(isDefined)
|
||||
.map((flatIndex) => ({
|
||||
id: flatIndex.id,
|
||||
isUnique: flatIndex.isUnique,
|
||||
indexFieldMetadatas: flatIndex.flatIndexFieldMetadatas,
|
||||
}));
|
||||
|
||||
const objectWithIndexes = {
|
||||
id: flatObjectMetadata.id,
|
||||
indexMetadatas,
|
||||
fields,
|
||||
};
|
||||
|
||||
const uniqueConstraints = getUniqueConstraintsFields<
|
||||
FlatFieldMetadata,
|
||||
typeof objectWithIndexes
|
||||
>(objectWithIndexes);
|
||||
|
||||
const inputFields: Record<
|
||||
string,
|
||||
{ type: GraphQLInputType; description: string }
|
||||
> = {};
|
||||
@@ -101,11 +134,11 @@ export class RelationConnectGqlInputTypeGenerator {
|
||||
});
|
||||
|
||||
const compositeInputType = new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${pascalCase(field.name)}WhereInput`,
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}${pascalCase(field.name)}WhereInput`,
|
||||
fields: () => compositeFields,
|
||||
});
|
||||
|
||||
fields[field.name] = {
|
||||
inputFields[field.name] = {
|
||||
type: compositeInputType,
|
||||
description: `Connect by ${field.label || field.name}`,
|
||||
};
|
||||
@@ -116,7 +149,7 @@ export class RelationConnectGqlInputTypeGenerator {
|
||||
{ settings: field.settings, isIdField: field.name === 'id' },
|
||||
);
|
||||
|
||||
fields[field.name] = {
|
||||
inputFields[field.name] = {
|
||||
type: scalarType || GraphQLString,
|
||||
description: `Connect by ${field.label || field.name}`,
|
||||
};
|
||||
@@ -127,15 +160,15 @@ export class RelationConnectGqlInputTypeGenerator {
|
||||
return {
|
||||
[RELATION_NESTED_QUERY_KEYWORDS.CONNECT_WHERE]: {
|
||||
type: new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}WhereUniqueInput`,
|
||||
fields: () => fields,
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}WhereUniqueInput`,
|
||||
fields: () => inputFields,
|
||||
}),
|
||||
description: `Find a ${objectMetadata.nameSingular} record based on its unique fields: ${this.formatConstraints(uniqueConstraints)}`,
|
||||
description: `Find a ${flatObjectMetadata.nameSingular} record based on its unique fields: ${this.formatConstraints(uniqueConstraints)}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private formatConstraints(constraints: FieldMetadataEntity[][]) {
|
||||
private formatConstraints(constraints: FlatFieldMetadata[][]) {
|
||||
return constraints
|
||||
.map((constraint) => constraint.map((field) => field.name).join(' and '))
|
||||
.join(' or ');
|
||||
|
||||
+18
-14
@@ -14,11 +14,11 @@ import {
|
||||
TypeOptions,
|
||||
} from 'src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
import { computeObjectMetadataInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-input-type.util';
|
||||
import { computeRelationConnectInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-relation-connect-input-type-key.util';
|
||||
import { extractGraphQLRelationFieldNames } from 'src/engine/api/graphql/workspace-schema-builder/utils/extract-graphql-relation-field-names.util';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
|
||||
@Injectable()
|
||||
export class RelationFieldMetadataGqlInputTypeGenerator {
|
||||
@@ -35,7 +35,7 @@ export class RelationFieldMetadataGqlInputTypeGenerator {
|
||||
fieldMetadata,
|
||||
typeOptions,
|
||||
}: {
|
||||
fieldMetadata: FieldMetadataEntity<
|
||||
fieldMetadata: FlatFieldMetadata<
|
||||
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
|
||||
>;
|
||||
typeOptions: TypeOptions;
|
||||
@@ -77,7 +77,7 @@ export class RelationFieldMetadataGqlInputTypeGenerator {
|
||||
fieldMetadata,
|
||||
typeOptions,
|
||||
}: {
|
||||
fieldMetadata: FieldMetadataEntity<
|
||||
fieldMetadata: FlatFieldMetadata<
|
||||
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
|
||||
>;
|
||||
typeOptions: TypeOptions;
|
||||
@@ -118,13 +118,13 @@ export class RelationFieldMetadataGqlInputTypeGenerator {
|
||||
public generateSimpleRelationFieldOrderByInputType({
|
||||
fieldMetadata,
|
||||
typeOptions,
|
||||
objectMetadataMaps,
|
||||
context,
|
||||
}: {
|
||||
fieldMetadata: FieldMetadataEntity<
|
||||
fieldMetadata: FlatFieldMetadata<
|
||||
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
|
||||
>;
|
||||
typeOptions: TypeOptions;
|
||||
objectMetadataMaps?: ObjectMetadataMaps;
|
||||
context?: SchemaGenerationContext;
|
||||
}) {
|
||||
if (fieldMetadata.settings?.relationType === RelationType.ONE_TO_MANY)
|
||||
return {};
|
||||
@@ -158,10 +158,12 @@ export class RelationFieldMetadataGqlInputTypeGenerator {
|
||||
|
||||
if (
|
||||
isDefined(fieldMetadata.relationTargetObjectMetadataId) &&
|
||||
isDefined(objectMetadataMaps)
|
||||
isDefined(context)
|
||||
) {
|
||||
const targetObjectMetadata =
|
||||
objectMetadataMaps.byId[fieldMetadata.relationTargetObjectMetadataId];
|
||||
context.flatObjectMetadataMaps.byId[
|
||||
fieldMetadata.relationTargetObjectMetadataId
|
||||
];
|
||||
|
||||
if (isDefined(targetObjectMetadata)) {
|
||||
const targetOrderByInputTypeKey = computeObjectMetadataInputTypeKey(
|
||||
@@ -189,10 +191,10 @@ export class RelationFieldMetadataGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
public generateSimpleRelationFieldGroupByInputType(
|
||||
fieldMetadata: FieldMetadataEntity<
|
||||
fieldMetadata: FlatFieldMetadata<
|
||||
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
|
||||
>,
|
||||
objectMetadataMaps?: ObjectMetadataMaps,
|
||||
context?: SchemaGenerationContext,
|
||||
): GraphQLInputFieldConfigMap {
|
||||
if (fieldMetadata.settings?.relationType === RelationType.ONE_TO_MANY)
|
||||
return {};
|
||||
@@ -204,10 +206,12 @@ export class RelationFieldMetadataGqlInputTypeGenerator {
|
||||
|
||||
if (
|
||||
isDefined(fieldMetadata.relationTargetObjectMetadataId) &&
|
||||
isDefined(objectMetadataMaps)
|
||||
isDefined(context)
|
||||
) {
|
||||
const targetObjectMetadata =
|
||||
objectMetadataMaps.byId[fieldMetadata.relationTargetObjectMetadataId];
|
||||
context.flatObjectMetadataMaps.byId[
|
||||
fieldMetadata.relationTargetObjectMetadataId
|
||||
];
|
||||
|
||||
if (isDefined(targetObjectMetadata)) {
|
||||
const targetGroupByInputTypeKey = computeObjectMetadataInputTypeKey(
|
||||
@@ -238,7 +242,7 @@ export class RelationFieldMetadataGqlInputTypeGenerator {
|
||||
fieldMetadata,
|
||||
typeOptions,
|
||||
}: {
|
||||
fieldMetadata: FieldMetadataEntity<
|
||||
fieldMetadata: FlatFieldMetadata<
|
||||
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
|
||||
>;
|
||||
typeOptions: TypeOptions;
|
||||
|
||||
+24
-13
@@ -15,14 +15,16 @@ import { GqlInputTypeDefinitionKind } from 'src/engine/api/graphql/workspace-sch
|
||||
import { RelationFieldMetadataGqlInputTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/input-types/relation-field-metadata-gql-type.generator';
|
||||
import { TypeMapperService } from 'src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
import { computeFieldInputTypeOptions } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-field-input-type-options.util';
|
||||
import { computeCompositeFieldInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-composite-field-input-type-key.util';
|
||||
import { computeEnumFieldGqlTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-enum-field-gql-type-key.util';
|
||||
import { computeObjectMetadataInputTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-input-type.util';
|
||||
import { isFieldMetadataRelationOrMorphRelation } from 'src/engine/api/graphql/workspace-schema-builder/utils/is-field-metadata-relation-or-morph-relation.utils';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { isEnumFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@Injectable()
|
||||
@@ -36,15 +38,20 @@ export class ObjectMetadataUpdateGqlInputTypeGenerator {
|
||||
private readonly typeMapperService: TypeMapperService,
|
||||
) {}
|
||||
|
||||
public buildAndStore(objectMetadata: ObjectMetadataEntity) {
|
||||
public buildAndStore(
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
fields: FlatFieldMetadata[],
|
||||
_context: SchemaGenerationContext,
|
||||
) {
|
||||
const inputType = new GraphQLInputObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.Update.toString()}Input`,
|
||||
description: objectMetadata.description,
|
||||
fields: () => this.generateFields(objectMetadata),
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}${GqlInputTypeDefinitionKind.Update.toString()}Input`,
|
||||
description: flatObjectMetadata.description,
|
||||
fields: () =>
|
||||
this.generateFields(flatObjectMetadata.nameSingular, fields),
|
||||
}) as GraphQLInputObjectType;
|
||||
|
||||
const key = computeObjectMetadataInputTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
GqlInputTypeDefinitionKind.Update,
|
||||
);
|
||||
|
||||
@@ -52,21 +59,25 @@ export class ObjectMetadataUpdateGqlInputTypeGenerator {
|
||||
}
|
||||
|
||||
private generateFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectNameSingular: string,
|
||||
fields: FlatFieldMetadata[],
|
||||
): GraphQLInputFieldConfigMap {
|
||||
const allGeneratedFields: GraphQLInputFieldConfigMap = {};
|
||||
|
||||
for (const fieldMetadata of objectMetadata.fields) {
|
||||
fieldMetadata.isNullable = true;
|
||||
for (const fieldMetadata of fields) {
|
||||
const modifiedFieldMetadata = {
|
||||
...fieldMetadata,
|
||||
isNullable: true,
|
||||
};
|
||||
|
||||
const typeOptions = computeFieldInputTypeOptions(
|
||||
fieldMetadata,
|
||||
modifiedFieldMetadata,
|
||||
GqlInputTypeDefinitionKind.Update,
|
||||
);
|
||||
|
||||
let generatedFields;
|
||||
|
||||
if (isFieldMetadataRelationOrMorphRelation(fieldMetadata)) {
|
||||
if (isMorphOrRelationFlatFieldMetadata(fieldMetadata)) {
|
||||
generatedFields = {
|
||||
...this.relationFieldMetadataGqlInputTypeGenerator.generateSimpleRelationFieldCreateOrUpdateInputType(
|
||||
{
|
||||
@@ -90,7 +101,7 @@ export class ObjectMetadataUpdateGqlInputTypeGenerator {
|
||||
|
||||
if (isEnumFieldMetadataType(fieldMetadata.type)) {
|
||||
const key = computeEnumFieldGqlTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
objectNameSingular,
|
||||
fieldMetadata.name,
|
||||
);
|
||||
|
||||
|
||||
+4
-5
@@ -4,18 +4,17 @@ import {
|
||||
type AggregationField,
|
||||
getAvailableAggregationsFromObjectFields,
|
||||
} from 'src/engine/api/graphql/workspace-schema-builder/utils/get-available-aggregations-from-object-fields.util';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
|
||||
type AggregationGraphQLType = Pick<AggregationField, 'type' | 'description'>;
|
||||
|
||||
@Injectable()
|
||||
export class AggregationObjectTypeGenerator {
|
||||
public generate(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
flatFields: FlatFieldMetadata[],
|
||||
): Record<string, AggregationGraphQLType> {
|
||||
const availableAggregations = getAvailableAggregationsFromObjectFields(
|
||||
objectMetadata.fields,
|
||||
);
|
||||
const availableAggregations =
|
||||
getAvailableAggregationsFromObjectFields(flatFields);
|
||||
|
||||
return Object.entries(availableAggregations).reduce<
|
||||
Record<string, AggregationGraphQLType>
|
||||
|
||||
+16
-14
@@ -10,7 +10,8 @@ import { TypeMapperService } from 'src/engine/api/graphql/workspace-schema-build
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { GraphQLOutputTypeFieldConfigMap } from 'src/engine/api/graphql/workspace-schema-builder/types/graphql-field-config-map.types';
|
||||
import { computeObjectMetadataObjectTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-object-type-key.util';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@Injectable()
|
||||
@@ -23,51 +24,52 @@ export class ConnectionGqlObjectTypeGenerator {
|
||||
private readonly gqlTypesStorage: GqlTypesStorage,
|
||||
) {}
|
||||
|
||||
public buildAndStore(objectMetadata: ObjectMetadataEntity) {
|
||||
public buildAndStore(
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
flatFields: FlatFieldMetadata[],
|
||||
) {
|
||||
const kind = ObjectTypeDefinitionKind.Connection;
|
||||
|
||||
const key = computeObjectMetadataObjectTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
kind,
|
||||
);
|
||||
|
||||
this.gqlTypesStorage.addGqlType(
|
||||
key,
|
||||
new GraphQLObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${kind.toString()}`,
|
||||
description: objectMetadata.description,
|
||||
fields: () => this.generateFields(objectMetadata),
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}${kind.toString()}`,
|
||||
description: flatObjectMetadata.description,
|
||||
fields: () => this.generateFields(flatObjectMetadata, flatFields),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private generateFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
flatFields: FlatFieldMetadata[],
|
||||
): GraphQLOutputTypeFieldConfigMap {
|
||||
const fields: GraphQLOutputTypeFieldConfigMap = {};
|
||||
|
||||
const aggregatedFields =
|
||||
this.aggregationObjectTypeGenerator.generate(objectMetadata);
|
||||
this.aggregationObjectTypeGenerator.generate(flatFields);
|
||||
|
||||
Object.assign(fields, aggregatedFields);
|
||||
|
||||
const edgeType = this.gqlTypesStorage.getGqlTypeByKey(
|
||||
computeObjectMetadataObjectTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
ObjectTypeDefinitionKind.Edge,
|
||||
),
|
||||
);
|
||||
|
||||
if (!isDefined(edgeType) || isInputObjectType(edgeType)) {
|
||||
this.logger.error(
|
||||
`Edge type for ${objectMetadata.nameSingular} was not found. Please, check if you have defined it.`,
|
||||
{
|
||||
objectMetadata,
|
||||
},
|
||||
`Edge type for ${flatObjectMetadata.nameSingular} was not found. Please, check if you have defined it.`,
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
`Edge type for ${objectMetadata.nameSingular} was not found. Please, check if you have defined it.`,
|
||||
`Edge type for ${flatObjectMetadata.nameSingular} was not found. Please, check if you have defined it.`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+10
-13
@@ -9,7 +9,7 @@ import { TypeMapperService } from 'src/engine/api/graphql/workspace-schema-build
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { GraphQLOutputTypeFieldConfigMap } from 'src/engine/api/graphql/workspace-schema-builder/types/graphql-field-config-map.types';
|
||||
import { computeObjectMetadataObjectTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-object-type-key.util';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@Injectable()
|
||||
@@ -21,30 +21,30 @@ export class EdgeGqlObjectTypeGenerator {
|
||||
private readonly gqlTypesStorage: GqlTypesStorage,
|
||||
) {}
|
||||
|
||||
public buildAndStore(objectMetadata: ObjectMetadataEntity) {
|
||||
public buildAndStore(flatObjectMetadata: FlatObjectMetadata) {
|
||||
const kind = ObjectTypeDefinitionKind.Edge;
|
||||
const key = computeObjectMetadataObjectTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
kind,
|
||||
);
|
||||
|
||||
this.gqlTypesStorage.addGqlType(
|
||||
key,
|
||||
new GraphQLObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${kind.toString()}`,
|
||||
description: objectMetadata.description,
|
||||
fields: () => this.generateFields(objectMetadata),
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}${kind.toString()}`,
|
||||
description: flatObjectMetadata.description,
|
||||
fields: () => this.generateFields(flatObjectMetadata.nameSingular),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private generateFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectNameSingular: string,
|
||||
): GraphQLOutputTypeFieldConfigMap {
|
||||
const fields: GraphQLOutputTypeFieldConfigMap = {};
|
||||
|
||||
const key = computeObjectMetadataObjectTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
objectNameSingular,
|
||||
ObjectTypeDefinitionKind.Plain,
|
||||
);
|
||||
|
||||
@@ -52,14 +52,11 @@ export class EdgeGqlObjectTypeGenerator {
|
||||
|
||||
if (!isDefined(objectType) || isInputObjectType(objectType)) {
|
||||
this.logger.error(
|
||||
`Node type for ${objectMetadata.nameSingular} was not found. Please, check if you have defined it.`,
|
||||
{
|
||||
objectMetadata,
|
||||
},
|
||||
`Node type for ${objectNameSingular} was not found. Please, check if you have defined it.`,
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
`Node type for ${objectMetadata.nameSingular} was not found. Please, check if you have defined it.`,
|
||||
`Node type for ${objectNameSingular} was not found. Please, check if you have defined it.`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+10
-13
@@ -9,7 +9,7 @@ import { TypeMapperService } from 'src/engine/api/graphql/workspace-schema-build
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { GraphQLOutputTypeFieldConfigMap } from 'src/engine/api/graphql/workspace-schema-builder/types/graphql-field-config-map.types';
|
||||
import { computeObjectMetadataObjectTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-object-type-key.util';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@Injectable()
|
||||
@@ -23,46 +23,43 @@ export class GroupByConnectionGqlObjectTypeGenerator {
|
||||
private readonly gqlTypesStorage: GqlTypesStorage,
|
||||
) {}
|
||||
|
||||
public buildAndStore(objectMetadata: ObjectMetadataEntity) {
|
||||
public buildAndStore(flatObjectMetadata: FlatObjectMetadata) {
|
||||
const kind = ObjectTypeDefinitionKind.GroupByConnection;
|
||||
|
||||
const key = computeObjectMetadataObjectTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
kind,
|
||||
);
|
||||
|
||||
this.gqlTypesStorage.addGqlType(
|
||||
key,
|
||||
new GraphQLObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${kind.toString()}`,
|
||||
description: objectMetadata.description,
|
||||
fields: () => this.generateFields(objectMetadata),
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}${kind.toString()}`,
|
||||
description: flatObjectMetadata.description,
|
||||
fields: () => this.generateFields(flatObjectMetadata.nameSingular),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private generateFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectNameSingular: string,
|
||||
): GraphQLOutputTypeFieldConfigMap {
|
||||
const fields: GraphQLOutputTypeFieldConfigMap = {};
|
||||
|
||||
const connection = this.gqlTypesStorage.getGqlTypeByKey(
|
||||
computeObjectMetadataObjectTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
objectNameSingular,
|
||||
ObjectTypeDefinitionKind.Connection,
|
||||
),
|
||||
);
|
||||
|
||||
if (!isDefined(connection) || !isObjectType(connection)) {
|
||||
this.logger.error(
|
||||
`Connection type for ${objectMetadata.nameSingular} was not found.`,
|
||||
{
|
||||
objectMetadata,
|
||||
},
|
||||
`Connection type for ${objectNameSingular} was not found.`,
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
`Connection type for ${objectMetadata.nameSingular} was not found.`,
|
||||
`Connection type for ${objectNameSingular} was not found.`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+20
-18
@@ -16,11 +16,11 @@ import { GraphQLOutputTypeFieldConfigMap } from 'src/engine/api/graphql/workspac
|
||||
import { computeCompositeFieldObjectTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-composite-field-object-type-key.util';
|
||||
import { computeEnumFieldGqlTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-enum-field-gql-type-key.util';
|
||||
import { computeObjectMetadataObjectTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-object-type-key.util';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { isEnumFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { isMorphOrRelationFieldMetadataType } from 'src/engine/utils/is-morph-or-relation-field-metadata-type.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { pascalCase } from 'src/utils/pascal-case';
|
||||
|
||||
@Injectable()
|
||||
@@ -35,29 +35,33 @@ export class ObjectMetadataGqlObjectTypeGenerator {
|
||||
private readonly typeMapperService: TypeMapperService,
|
||||
) {}
|
||||
|
||||
public buildAndStore(objectMetadata: ObjectMetadataEntity) {
|
||||
public buildAndStore(
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
fields: FlatFieldMetadata[],
|
||||
) {
|
||||
const kind = ObjectTypeDefinitionKind.Plain;
|
||||
const key = computeObjectMetadataObjectTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
ObjectTypeDefinitionKind.Plain,
|
||||
);
|
||||
|
||||
this.gqlTypesStorage.addGqlType(
|
||||
key,
|
||||
new GraphQLObjectType({
|
||||
name: `${pascalCase(objectMetadata.nameSingular)}${kind.toString()}`,
|
||||
description: objectMetadata.description,
|
||||
fields: this.generateFields(objectMetadata),
|
||||
name: `${pascalCase(flatObjectMetadata.nameSingular)}${kind.toString()}`,
|
||||
description: flatObjectMetadata.description,
|
||||
fields: this.generateFields(flatObjectMetadata.nameSingular, fields),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private generateFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectNameSingular: string,
|
||||
fields: FlatFieldMetadata[],
|
||||
): GraphQLOutputTypeFieldConfigMap {
|
||||
const allGeneratedFields: GraphQLOutputTypeFieldConfigMap = {};
|
||||
|
||||
for (const field of objectMetadata.fields) {
|
||||
for (const field of fields) {
|
||||
const typeFactoryOptions = {
|
||||
nullable: field.isNullable ?? undefined,
|
||||
isArray: field.type === FieldMetadataType.MULTI_SELECT,
|
||||
@@ -66,13 +70,11 @@ export class ObjectMetadataGqlObjectTypeGenerator {
|
||||
isIdField: false,
|
||||
};
|
||||
|
||||
if (isMorphOrRelationFieldMetadataType(field.type)) {
|
||||
if (isMorphOrRelationFlatFieldMetadata(field)) {
|
||||
const relationFieldObjectType =
|
||||
this.relationFieldMetadataGqlObjectTypeGenerator.generateRelationFieldObjectType(
|
||||
{
|
||||
fieldMetadata: field as FieldMetadataEntity<
|
||||
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
|
||||
>,
|
||||
fieldMetadata: field,
|
||||
typeOptions: typeFactoryOptions,
|
||||
},
|
||||
);
|
||||
@@ -96,7 +98,7 @@ export class ObjectMetadataGqlObjectTypeGenerator {
|
||||
!isDefined(compositeFieldObjectType) ||
|
||||
isInputObjectType(compositeFieldObjectType)
|
||||
) {
|
||||
const message = `Could not find a GraphQL output type for ${field.name} composite field metadata of object ${objectMetadata.nameSingular}`;
|
||||
const message = `Could not find a GraphQL output type for ${field.name} composite field metadata of object ${objectNameSingular}`;
|
||||
|
||||
this.logger.error(message, {
|
||||
type: field.type,
|
||||
@@ -109,7 +111,7 @@ export class ObjectMetadataGqlObjectTypeGenerator {
|
||||
type = compositeFieldObjectType;
|
||||
} else if (isEnumFieldMetadataType(field.type)) {
|
||||
const enumFieldEnumTypeKey = computeEnumFieldGqlTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
objectNameSingular,
|
||||
field.name,
|
||||
);
|
||||
|
||||
@@ -120,7 +122,7 @@ export class ObjectMetadataGqlObjectTypeGenerator {
|
||||
!isDefined(enumFieldEnumType) ||
|
||||
isInputObjectType(enumFieldEnumType)
|
||||
) {
|
||||
const message = `Could not find a GraphQL output type for ${field.name} enum field metadata of object ${objectMetadata.nameSingular}`;
|
||||
const message = `Could not find a GraphQL output type for ${field.name} enum field metadata of object ${objectNameSingular}`;
|
||||
|
||||
this.logger.error(message, {
|
||||
type: field.type,
|
||||
@@ -138,7 +140,7 @@ export class ObjectMetadataGqlObjectTypeGenerator {
|
||||
);
|
||||
|
||||
if (!isDefined(type)) {
|
||||
const message = `Could not find a GraphQL output type for ${field.name} scalar field metadata of object ${objectMetadata.nameSingular}`;
|
||||
const message = `Could not find a GraphQL output type for ${field.name} scalar field metadata of object ${objectNameSingular}`;
|
||||
|
||||
this.logger.error(message, {
|
||||
type: field.type,
|
||||
|
||||
+49
-59
@@ -15,12 +15,13 @@ import { ObjectTypeDefinitionKind } from 'src/engine/api/graphql/workspace-schem
|
||||
import { ArgsTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/args-type/args-type.generator';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { GraphQLOutputTypeFieldConfigMap } from 'src/engine/api/graphql/workspace-schema-builder/types/graphql-field-config-map.types';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
import { computeObjectMetadataObjectTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-object-type-key.util';
|
||||
import { getResolverArgs } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-resolver-args.util';
|
||||
import { objectContainsRelationField } from 'src/engine/api/graphql/workspace-schema-builder/utils/object-contains-relation-field';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { isFieldMetadataEntityOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { isMorphOrRelationFieldMetadataType } from 'src/engine/utils/is-morph-or-relation-field-metadata-type.util';
|
||||
|
||||
@Injectable()
|
||||
export class ObjectMetadataWithRelationsGqlObjectTypeGenerator {
|
||||
@@ -34,11 +35,12 @@ export class ObjectMetadataWithRelationsGqlObjectTypeGenerator {
|
||||
) {}
|
||||
|
||||
public buildAndStore(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectMetadataCollection: ObjectMetadataEntity[],
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
flatFieldMetadatas: FlatFieldMetadata[],
|
||||
context: SchemaGenerationContext,
|
||||
) {
|
||||
const key = computeObjectMetadataObjectTypeKey(
|
||||
objectMetadata.nameSingular,
|
||||
flatObjectMetadata.nameSingular,
|
||||
ObjectTypeDefinitionKind.Plain,
|
||||
);
|
||||
|
||||
@@ -46,28 +48,26 @@ export class ObjectMetadataWithRelationsGqlObjectTypeGenerator {
|
||||
|
||||
if (!isDefined(gqlType) || !isObjectType(gqlType)) {
|
||||
this.logger.error(
|
||||
`Could not find a GraphQL type for ${objectMetadata.id.toString()}`,
|
||||
{
|
||||
objectMetadata,
|
||||
},
|
||||
`Could not find a GraphQL type for ${flatObjectMetadata.id.toString()}`,
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
`Could not find a GraphQL type for ${objectMetadata.id.toString()}`,
|
||||
`Could not find a GraphQL type for ${flatObjectMetadata.id.toString()}`,
|
||||
);
|
||||
}
|
||||
|
||||
const containsRelationOrMorphField = flatFieldMetadatas.some((field) =>
|
||||
isMorphOrRelationFieldMetadataType(field.type),
|
||||
);
|
||||
|
||||
// Security check to avoid extending an object that does not need to be extended
|
||||
if (!objectContainsRelationField(objectMetadata)) {
|
||||
if (!containsRelationOrMorphField) {
|
||||
this.logger.error(
|
||||
`This object does not need to be extended: ${objectMetadata.id.toString()}`,
|
||||
{
|
||||
objectMetadata,
|
||||
},
|
||||
`This object does not need to be extended: ${flatObjectMetadata.id.toString()}`,
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
`This object does not need to be extended: ${objectMetadata.id.toString()}`,
|
||||
`This object does not need to be extended: ${flatObjectMetadata.id.toString()}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,66 +81,57 @@ export class ObjectMetadataWithRelationsGqlObjectTypeGenerator {
|
||||
...config,
|
||||
fields: () => ({
|
||||
...config.fields,
|
||||
...this.generateFields(objectMetadata, objectMetadataCollection),
|
||||
...this.generateFields(flatFieldMetadatas, context),
|
||||
}),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private generateFields(
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
objectMetadataCollection: ObjectMetadataEntity[],
|
||||
flatFieldMetadatas: FlatFieldMetadata[],
|
||||
context: SchemaGenerationContext,
|
||||
): GraphQLOutputTypeFieldConfigMap {
|
||||
const fields: GraphQLOutputTypeFieldConfigMap = {};
|
||||
const outputFields: GraphQLOutputTypeFieldConfigMap = {};
|
||||
|
||||
for (const fieldMetadata of objectMetadata.fields) {
|
||||
// Ignore non-relation fields as they are already defined
|
||||
const isRelation =
|
||||
isFieldMetadataEntityOfType(
|
||||
fieldMetadata,
|
||||
FieldMetadataType.RELATION,
|
||||
) ||
|
||||
isFieldMetadataEntityOfType(
|
||||
fieldMetadata,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
);
|
||||
|
||||
if (!isRelation) {
|
||||
for (const flatFieldMetadata of flatFieldMetadatas) {
|
||||
if (!isMorphOrRelationFlatFieldMetadata(flatFieldMetadata)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!fieldMetadata.settings) {
|
||||
if (!flatFieldMetadata.settings) {
|
||||
throw new Error(
|
||||
`Field Metadata of type RELATION or MORPH_RELATION with id ${fieldMetadata.id} has no settings`,
|
||||
`Field Metadata of type RELATION or MORPH_RELATION with id ${flatFieldMetadata.id} has no settings`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!fieldMetadata.relationTargetObjectMetadataId) {
|
||||
if (!flatFieldMetadata.relationTargetObjectMetadataId) {
|
||||
throw new Error(
|
||||
`Field Metadata of type RELATION or MORPH_RELATION with id ${fieldMetadata.id} has no relation target object metadata id`,
|
||||
`Field Metadata of type RELATION or MORPH_RELATION with id ${flatFieldMetadata.id} has no relation target object metadata id`,
|
||||
);
|
||||
}
|
||||
|
||||
const objectMetadataTarget = objectMetadataCollection.find(
|
||||
(objectMetadata) =>
|
||||
objectMetadata.id === fieldMetadata.relationTargetObjectMetadataId,
|
||||
);
|
||||
const objectMetadataTarget =
|
||||
context.flatObjectMetadataMaps.byId[
|
||||
flatFieldMetadata.relationTargetObjectMetadataId
|
||||
];
|
||||
|
||||
if (!isDefined(objectMetadataTarget)) {
|
||||
throw new Error(
|
||||
`Field Metadata of type RELATION or MORPH_RELATION with id ${fieldMetadata.id} has no relation target object metadata`,
|
||||
`Field Metadata of type RELATION or MORPH_RELATION with id ${flatFieldMetadata.id} has no relation target object metadata`,
|
||||
);
|
||||
}
|
||||
|
||||
const targetObjectMetadataGqlObjectType =
|
||||
this.fetchTargetObjectMetadataGqlObjectType(
|
||||
fieldMetadata,
|
||||
flatFieldMetadata,
|
||||
objectMetadataTarget,
|
||||
);
|
||||
|
||||
let argsType: GraphQLFieldConfigArgumentMap | undefined = undefined;
|
||||
|
||||
if (fieldMetadata.settings.relationType === RelationType.ONE_TO_MANY) {
|
||||
if (
|
||||
flatFieldMetadata.settings?.relationType === RelationType.ONE_TO_MANY
|
||||
) {
|
||||
const args = getResolverArgs('findMany');
|
||||
|
||||
argsType = this.argsTypeGenerator.generate({
|
||||
@@ -149,31 +140,31 @@ export class ObjectMetadataWithRelationsGqlObjectTypeGenerator {
|
||||
});
|
||||
}
|
||||
|
||||
fields[fieldMetadata.name] = {
|
||||
outputFields[flatFieldMetadata.name] = {
|
||||
type: targetObjectMetadataGqlObjectType,
|
||||
args: argsType,
|
||||
description: fieldMetadata.description,
|
||||
description: flatFieldMetadata.description,
|
||||
};
|
||||
}
|
||||
|
||||
return fields;
|
||||
return outputFields;
|
||||
}
|
||||
|
||||
private fetchTargetObjectMetadataGqlObjectType(
|
||||
fieldMetadata: FieldMetadataEntity<
|
||||
flatFieldMetadata: FlatFieldMetadata<
|
||||
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
|
||||
>,
|
||||
objectMetadataTarget: ObjectMetadataEntity,
|
||||
objectMetadataTarget: FlatObjectMetadata,
|
||||
): GraphQLOutputType {
|
||||
if (!fieldMetadata.settings) {
|
||||
if (!flatFieldMetadata.settings) {
|
||||
throw new Error(
|
||||
`Field Metadata of type RELATION or MORPH_RELATION with id ${fieldMetadata.id} has no settings`,
|
||||
`Field Metadata of type RELATION or MORPH_RELATION with id ${flatFieldMetadata.id} has no settings`,
|
||||
);
|
||||
}
|
||||
|
||||
const key = computeObjectMetadataObjectTypeKey(
|
||||
objectMetadataTarget.nameSingular,
|
||||
fieldMetadata.settings.relationType === RelationType.ONE_TO_MANY
|
||||
flatFieldMetadata.settings.relationType === RelationType.ONE_TO_MANY
|
||||
? ObjectTypeDefinitionKind.Connection
|
||||
: ObjectTypeDefinitionKind.Plain,
|
||||
);
|
||||
@@ -186,13 +177,12 @@ export class ObjectMetadataWithRelationsGqlObjectTypeGenerator {
|
||||
!isObjectType(targetObjectMetadataGqlObjectType)
|
||||
) {
|
||||
this.logger.error(
|
||||
`Could not find a relation type for ${fieldMetadata.id}`,
|
||||
{
|
||||
fieldMetadata,
|
||||
},
|
||||
`Could not find a relation type for ${flatFieldMetadata.id}`,
|
||||
);
|
||||
|
||||
throw new Error(`Could not find a relation type for ${fieldMetadata.id}`);
|
||||
throw new Error(
|
||||
`Could not find a relation type for ${flatFieldMetadata.id}`,
|
||||
);
|
||||
}
|
||||
|
||||
return targetObjectMetadataGqlObjectType;
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ import {
|
||||
TypeOptions,
|
||||
} from 'src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service';
|
||||
import { extractGraphQLRelationFieldNames } from 'src/engine/api/graphql/workspace-schema-builder/utils/extract-graphql-relation-field-names.util';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
|
||||
@Injectable()
|
||||
export class RelationFieldMetadataGqlObjectTypeGenerator {
|
||||
@@ -22,7 +22,7 @@ export class RelationFieldMetadataGqlObjectTypeGenerator {
|
||||
fieldMetadata,
|
||||
typeOptions,
|
||||
}: {
|
||||
fieldMetadata: FieldMetadataEntity<
|
||||
fieldMetadata: FlatFieldMetadata<
|
||||
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
|
||||
>;
|
||||
typeOptions: TypeOptions;
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ import { workspaceResolverBuilderMethodNames } from 'src/engine/api/graphql/work
|
||||
import { GqlOperation } from 'src/engine/api/graphql/workspace-schema-builder/enums/gql-operation.enum';
|
||||
import { RootTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/root-types/root-type.generator';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
|
||||
@Injectable()
|
||||
export class MutationTypeGenerator {
|
||||
@@ -15,9 +15,9 @@ export class MutationTypeGenerator {
|
||||
private readonly gqlTypesStorage: GqlTypesStorage,
|
||||
) {}
|
||||
|
||||
buildAndStore(objectMetadataCollection: ObjectMetadataEntity[]) {
|
||||
buildAndStore(context: SchemaGenerationContext) {
|
||||
return this.rootTypeGenerator.buildAndStore(
|
||||
objectMetadataCollection,
|
||||
context,
|
||||
[...workspaceResolverBuilderMethodNames.mutations],
|
||||
GqlOperation.Mutation,
|
||||
);
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ import { workspaceResolverBuilderMethodNames } from 'src/engine/api/graphql/work
|
||||
import { GqlOperation } from 'src/engine/api/graphql/workspace-schema-builder/enums/gql-operation.enum';
|
||||
import { RootTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/root-types/root-type.generator';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
|
||||
@Injectable()
|
||||
export class QueryTypeGenerator {
|
||||
@@ -15,9 +15,9 @@ export class QueryTypeGenerator {
|
||||
private readonly gqlTypesStorage: GqlTypesStorage,
|
||||
) {}
|
||||
|
||||
async buildAndStore(objectMetadataCollection: ObjectMetadataEntity[]) {
|
||||
async buildAndStore(context: SchemaGenerationContext) {
|
||||
return this.rootTypeGenerator.buildAndStore(
|
||||
objectMetadataCollection,
|
||||
context,
|
||||
workspaceResolverBuilderMethodNames.queries,
|
||||
GqlOperation.Query,
|
||||
);
|
||||
|
||||
+8
-3
@@ -11,10 +11,11 @@ import { ObjectTypeDefinitionKind } from 'src/engine/api/graphql/workspace-schem
|
||||
import { ArgsTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/args-type/args-type.generator';
|
||||
import { TypeMapperService } from 'src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service';
|
||||
import { GqlTypesStorage } from 'src/engine/api/graphql/workspace-schema-builder/storages/gql-types.storage';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
import { GraphQLRootTypeFieldConfigMap } from 'src/engine/api/graphql/workspace-schema-builder/types/graphql-field-config-map.types';
|
||||
import { computeObjectMetadataObjectTypeKey } from 'src/engine/api/graphql/workspace-schema-builder/utils/compute-stored-gql-type-key-utils/compute-object-metadata-object-type-key.util';
|
||||
import { getResolverArgs } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-resolver-args.util';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { getResolverName } from 'src/engine/utils/get-resolver-name.util';
|
||||
|
||||
@Injectable()
|
||||
@@ -29,7 +30,7 @@ export class RootTypeGenerator {
|
||||
) {}
|
||||
|
||||
buildAndStore(
|
||||
objectMetadataCollection: ObjectMetadataEntity[],
|
||||
context: SchemaGenerationContext,
|
||||
workspaceResolverMethodNames: readonly WorkspaceResolverBuilderMethodNames[],
|
||||
objectTypeName: GqlOperation,
|
||||
) {
|
||||
@@ -47,6 +48,10 @@ export class RootTypeGenerator {
|
||||
);
|
||||
}
|
||||
|
||||
const objectMetadataCollection = Object.values(
|
||||
context.flatObjectMetadataMaps.byId,
|
||||
).filter(isDefined);
|
||||
|
||||
this.gqlTypesStorage.addGqlType(
|
||||
objectTypeName,
|
||||
new GraphQLObjectType({
|
||||
@@ -60,7 +65,7 @@ export class RootTypeGenerator {
|
||||
}
|
||||
|
||||
private generateFields(
|
||||
objectMetadataCollection: ObjectMetadataEntity[],
|
||||
objectMetadataCollection: FlatObjectMetadata[],
|
||||
workspaceResolverMethodNames: readonly WorkspaceResolverBuilderMethodNames[],
|
||||
): GraphQLRootTypeFieldConfigMap {
|
||||
const fieldConfigMap: GraphQLRootTypeFieldConfigMap = {};
|
||||
|
||||
+7
-4
@@ -1,9 +1,12 @@
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
|
||||
import { type ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
|
||||
export interface WorkspaceSchemaBuilderContext {
|
||||
authContext: AuthContext;
|
||||
objectMetadataMaps: ObjectMetadataMaps;
|
||||
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps;
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
objectIdByNameSingular: Record<string, string>;
|
||||
}
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
|
||||
export type SchemaGenerationContext = {
|
||||
flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
flatIndexMaps: FlatEntityMaps<FlatIndexMetadata>;
|
||||
};
|
||||
+4
-4
@@ -2,15 +2,15 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { GqlInputTypeDefinitionKind } from 'src/engine/api/graphql/workspace-schema-builder/enums/gql-input-type-definition-kind.enum';
|
||||
import { type TypeOptions } from 'src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service';
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
|
||||
export const computeFieldInputTypeOptions = <T extends FieldMetadataType>(
|
||||
fieldMetadata: FieldMetadataEntity<T>,
|
||||
export const computeFieldInputTypeOptions = (
|
||||
fieldMetadata: FlatFieldMetadata,
|
||||
kind: GqlInputTypeDefinitionKind,
|
||||
): TypeOptions => {
|
||||
return {
|
||||
nullable: fieldMetadata.isNullable ?? undefined,
|
||||
defaultValue: fieldMetadata.defaultValue,
|
||||
defaultValue: fieldMetadata.defaultValue ?? undefined,
|
||||
isArray:
|
||||
kind !== GqlInputTypeDefinitionKind.Filter &&
|
||||
fieldMetadata.type === FieldMetadataType.MULTI_SELECT,
|
||||
|
||||
+4
-3
@@ -1,13 +1,14 @@
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
|
||||
export const extractGraphQLRelationFieldNames = (
|
||||
fieldMetadata: FieldMetadataEntity<
|
||||
fieldMetadata: FlatFieldMetadata<
|
||||
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
|
||||
>,
|
||||
) => {
|
||||
const joinColumnName = fieldMetadata.settings?.joinColumnName;
|
||||
const settings = fieldMetadata.settings;
|
||||
const joinColumnName = settings?.joinColumnName;
|
||||
|
||||
if (!joinColumnName) {
|
||||
throw new Error('Join column name is not defined');
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { capitalize, isFieldMetadataDateKind } from 'twenty-shared/utils';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { getSubfieldsForAggregateOperation } from 'src/engine/twenty-orm/utils/get-subfields-for-aggregate-operation.util';
|
||||
|
||||
export type AggregationField = {
|
||||
@@ -20,7 +20,7 @@ export type AggregationField = {
|
||||
};
|
||||
|
||||
export const getAvailableAggregationsFromObjectFields = (
|
||||
fields: FieldMetadataEntity[],
|
||||
fields: FlatFieldMetadata[],
|
||||
): Record<string, AggregationField> => {
|
||||
return fields.reduce<Record<string, AggregationField>>(
|
||||
(acc, field) => {
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
|
||||
export const getFlatFieldsFromFlatObjectMetadata = (
|
||||
flatObjectMetadata: FlatObjectMetadata,
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>,
|
||||
): FlatFieldMetadata[] => {
|
||||
return flatObjectMetadata.fieldMetadataIds
|
||||
.map((fieldId) => flatFieldMetadataMaps.byId[fieldId])
|
||||
.filter(isDefined);
|
||||
};
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { isMorphRelationFieldMetadataType } from 'src/engine/utils/is-morph-relation-field-metadata-type.util';
|
||||
|
||||
export const objectContainsMorphRelationField = (
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
): boolean => {
|
||||
return objectMetadata.fields.some((field) =>
|
||||
isMorphRelationFieldMetadataType(field.type),
|
||||
);
|
||||
};
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { isMorphOrRelationFieldMetadataType } from 'src/engine/utils/is-morph-or-relation-field-metadata-type.util';
|
||||
|
||||
export const objectContainsRelationField = (
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
): boolean => {
|
||||
return objectMetadata.fields.some((field) =>
|
||||
isMorphOrRelationFieldMetadataType(field.type),
|
||||
);
|
||||
};
|
||||
+3
-3
@@ -6,7 +6,7 @@ import { GqlTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builde
|
||||
import { OrphanedTypesGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/orphaned-types.generator';
|
||||
import { MutationTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/root-types/mutation-type.generator';
|
||||
import { QueryTypeGenerator } from 'src/engine/api/graphql/workspace-schema-builder/graphql-type-generators/root-types/query-type.generator';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type SchemaGenerationContext } from 'src/engine/api/graphql/workspace-schema-builder/types/schema-generation-context.type';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceGraphQLSchemaGenerator {
|
||||
@@ -18,9 +18,9 @@ export class WorkspaceGraphQLSchemaGenerator {
|
||||
) {}
|
||||
|
||||
async generateSchema(
|
||||
objectMetadataCollection: ObjectMetadataEntity[],
|
||||
context: SchemaGenerationContext,
|
||||
): Promise<GraphQLSchema> {
|
||||
await this.gqlTypeGenerator.buildAndStore(objectMetadataCollection);
|
||||
await this.gqlTypeGenerator.buildAndStore(context);
|
||||
|
||||
// Assemble schema
|
||||
const schema = new GraphQLSchema({
|
||||
|
||||
Reference in New Issue
Block a user