111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
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 relationDirection = deduceRelationDirection(
|
|
fieldMetadata.objectMetadataId,
|
|
relationMetadata,
|
|
);
|
|
const referencedObjectMetadata =
|
|
relationDirection == RelationDirection.TO
|
|
? relationMetadata.fromObjectMetadata
|
|
: relationMetadata.toObjectMetadata;
|
|
|
|
// 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}: ${referencedObjectMetadata.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} {
|
|
${this.fieldsStringFactory.createFieldsStringRecursive(
|
|
info,
|
|
fieldValue,
|
|
referencedObjectMetadata.fields ?? [],
|
|
)}
|
|
}
|
|
`;
|
|
}
|
|
}
|