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,97 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { GraphQLResolveInfo } from 'graphql';
|
||||
import graphqlFields from 'graphql-fields';
|
||||
import isEmpty from 'lodash.isempty';
|
||||
|
||||
import { FieldMetadataInterface } from 'src/tenant/schema-builder/interfaces/field-metadata.interface';
|
||||
|
||||
import { isCompositeFieldMetadataType } from 'src/tenant/utils/is-composite-field-metadata-type.util';
|
||||
|
||||
import { FieldAliasFacotry } from './field-alias.factory';
|
||||
import { CompositeFieldAliasFactory } from './composite-field-alias.factory';
|
||||
|
||||
@Injectable()
|
||||
export class FieldsStringFactory {
|
||||
private readonly logger = new Logger(FieldsStringFactory.name);
|
||||
|
||||
constructor(
|
||||
private readonly fieldAliasFactory: FieldAliasFacotry,
|
||||
private readonly compositeFieldAliasFactory: CompositeFieldAliasFactory,
|
||||
) {}
|
||||
|
||||
create(
|
||||
info: GraphQLResolveInfo,
|
||||
fieldMetadataCollection: FieldMetadataInterface[],
|
||||
) {
|
||||
const selectedFields: Record<string, any> = graphqlFields(info);
|
||||
|
||||
return this.createFieldsStringRecursive(
|
||||
info,
|
||||
selectedFields,
|
||||
fieldMetadataCollection,
|
||||
);
|
||||
}
|
||||
|
||||
createFieldsStringRecursive(
|
||||
info: GraphQLResolveInfo,
|
||||
selectedFields: Record<string, any>,
|
||||
fieldMetadataCollection: FieldMetadataInterface[],
|
||||
accumulator = '',
|
||||
): string {
|
||||
const fieldMetadataMap = new Map(
|
||||
fieldMetadataCollection.map((metadata) => [metadata.name, metadata]),
|
||||
);
|
||||
|
||||
for (const [fieldKey, fieldValue] of Object.entries(selectedFields)) {
|
||||
let fieldAlias: string | null;
|
||||
|
||||
if (fieldMetadataMap.has(fieldKey)) {
|
||||
// We're sure that the field exists in the map after this if condition
|
||||
// ES6 should tackle that more properly
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const fieldMetadata = fieldMetadataMap.get(fieldKey)!;
|
||||
|
||||
// If the field is a composite field, we need to create a special alias
|
||||
if (isCompositeFieldMetadataType(fieldMetadata.type)) {
|
||||
const alias = this.compositeFieldAliasFactory.create(
|
||||
fieldKey,
|
||||
fieldValue,
|
||||
fieldMetadata,
|
||||
info,
|
||||
);
|
||||
|
||||
fieldAlias = alias;
|
||||
} else {
|
||||
// Otherwise we just need to create a simple alias
|
||||
const alias = this.fieldAliasFactory.create(fieldKey, fieldMetadata);
|
||||
|
||||
fieldAlias = alias;
|
||||
}
|
||||
}
|
||||
|
||||
fieldAlias ??= fieldKey;
|
||||
|
||||
// Recurse if value is a nested object, otherwise append field or alias
|
||||
if (
|
||||
!fieldMetadataMap.has(fieldKey) &&
|
||||
fieldValue &&
|
||||
typeof fieldValue === 'object' &&
|
||||
!isEmpty(fieldValue)
|
||||
) {
|
||||
accumulator += `${fieldKey} {\n`;
|
||||
accumulator = this.createFieldsStringRecursive(
|
||||
info,
|
||||
fieldValue,
|
||||
fieldMetadataCollection,
|
||||
accumulator,
|
||||
);
|
||||
accumulator += `}\n`;
|
||||
} else {
|
||||
accumulator += `${fieldAlias}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user