feat: schema-builder and resolver-builder can handle relations (#2398)
* feat: wip add relation * feat: add relation for custom and standards objects * fix: use enum instead of magic string * fix: remove dead code & fix tests * fix: typo * fix: BooleanFilter is missing * fix: Malformed result error
This commit is contained in:
@ -0,0 +1,108 @@
|
||||
import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { GraphQLResolveInfo } from 'graphql';
|
||||
|
||||
import { FieldMetadataInterface } from 'src/tenant/schema-builder/interfaces/field-metadata.interface';
|
||||
|
||||
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity';
|
||||
import { isCompositeFieldMetadataType } from 'src/tenant/utils/is-composite-field-metadata-type.util';
|
||||
import { RelationMetadataType } from 'src/metadata/relation-metadata/relation-metadata.entity';
|
||||
import {
|
||||
deduceRelationDirection,
|
||||
RelationDirection,
|
||||
} from 'src/tenant/utils/deduce-relation-direction.util';
|
||||
import { getFieldArgumentsByKey } from 'src/tenant/query-builder/utils/get-field-arguments-by-key.util';
|
||||
|
||||
import { FieldsStringFactory } from './fields-string.factory';
|
||||
import { ArgsStringFactory } from './args-string.factory';
|
||||
|
||||
@Injectable()
|
||||
export class CompositeFieldAliasFactory {
|
||||
private logger = new Logger(CompositeFieldAliasFactory.name);
|
||||
|
||||
constructor(
|
||||
@Inject(forwardRef(() => FieldsStringFactory))
|
||||
private readonly fieldsStringFactory: FieldsStringFactory,
|
||||
private readonly argsStringFactory: ArgsStringFactory,
|
||||
) {}
|
||||
|
||||
create(
|
||||
fieldKey: string,
|
||||
fieldValue: any,
|
||||
fieldMetadata: FieldMetadataInterface,
|
||||
info: GraphQLResolveInfo,
|
||||
) {
|
||||
if (!isCompositeFieldMetadataType(fieldMetadata.type)) {
|
||||
throw new Error(`Field ${fieldMetadata.name} is not a composite field`);
|
||||
}
|
||||
|
||||
switch (fieldMetadata.type) {
|
||||
case FieldMetadataType.RELATION:
|
||||
return this.createRelationAlias(
|
||||
fieldKey,
|
||||
fieldValue,
|
||||
fieldMetadata,
|
||||
info,
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private createRelationAlias(
|
||||
fieldKey: string,
|
||||
fieldValue: any,
|
||||
fieldMetadata: FieldMetadataInterface,
|
||||
info: GraphQLResolveInfo,
|
||||
) {
|
||||
const relationMetadata =
|
||||
fieldMetadata.fromRelationMetadata ?? fieldMetadata.toRelationMetadata;
|
||||
|
||||
if (!relationMetadata) {
|
||||
throw new Error(
|
||||
`Relation metadata not found for field ${fieldMetadata.name}`,
|
||||
);
|
||||
}
|
||||
|
||||
const targetTableName = relationMetadata.toObjectMetadata.targetTableName;
|
||||
const relationDirection = deduceRelationDirection(
|
||||
fieldMetadata.objectId,
|
||||
relationMetadata,
|
||||
);
|
||||
|
||||
// If it's a relation destination is of kind MANY, we need to add the collection suffix and extract the args
|
||||
if (
|
||||
relationMetadata.relationType === RelationMetadataType.ONE_TO_MANY &&
|
||||
relationDirection === RelationDirection.FROM
|
||||
) {
|
||||
const args = getFieldArgumentsByKey(info, fieldKey);
|
||||
const argsString = this.argsStringFactory.create(
|
||||
args,
|
||||
relationMetadata.toObjectMetadata.fields,
|
||||
);
|
||||
|
||||
return `
|
||||
${fieldKey}: ${targetTableName}Collection${
|
||||
argsString ? `(${argsString})` : ''
|
||||
} {
|
||||
${this.fieldsStringFactory.createFieldsStringRecursive(
|
||||
info,
|
||||
fieldValue,
|
||||
relationMetadata.toObjectMetadata.fields,
|
||||
)}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
// Otherwise it means it's a relation destination is of kind ONE
|
||||
return `
|
||||
${fieldKey}: ${targetTableName} {
|
||||
${this.fieldsStringFactory.createFieldsStringRecursive(
|
||||
info,
|
||||
fieldValue,
|
||||
relationMetadata.toObjectMetadata.fields,
|
||||
)}
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user