From 474db1e1420a81460fbfb5ab016ebaeaea11003a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20M?= Date: Fri, 1 Dec 2023 15:26:48 +0100 Subject: [PATCH] fix: nested relations not working and relations not prefixed (#2782) * fix: nested relations n+n * fix: prefix custom relations * fix: only apply targetColumnMap when it's a custom object * fix: force workspaceId to be provided * fix: toIsCustom -> isToCustom * fix: remove console.log --- .../field-metadata/field-metadata.service.ts | 22 ++++-- .../hooks/before-delete-one-field.hook.ts | 9 +-- .../hooks/before-update-one-field.hook.ts | 9 +-- .../interfaces/field-metadata.interface.ts | 1 + .../utils/generate-target-column-map.util.ts | 5 +- .../hooks/before-delete-one-object.hook.ts | 9 +-- .../hooks/before-update-one-object.hook.ts | 9 +-- .../object-metadata.service.ts | 49 +++++++------- .../hooks/before-delete-one-field.hook.ts | 9 +-- .../relation-metadata.service.ts | 40 ++++++++--- .../utils/create-custom-column-name.util.ts | 3 + .../factories/create-many-query.factory.ts | 4 +- .../factories/delete-many-query.factory.ts | 7 +- .../factories/delete-one-query.factory.ts | 7 +- .../factories/fields-string.factory.ts | 10 +-- .../factories/find-many-query.factory.ts | 4 +- .../factories/find-one-query.factory.ts | 4 +- .../factories/relation-field-alias.factory.ts | 67 ++++++++++++++----- .../factories/update-many-query.factory.ts | 4 +- .../factories/update-one-query.factory.ts | 4 +- .../workspace-query-builder.factory.ts | 14 ++-- .../workspace-query-builder.module.ts | 4 +- .../workspace-query-runner.service.ts | 41 ++++++++---- .../factories/args.factory.ts | 10 +-- .../extend-object-type-definition.factory.ts | 2 +- .../factories/root-type.factory.ts | 2 +- .../interfaces/param-metadata.interface.ts | 4 +- server/src/workspace/workspace.factory.ts | 4 +- 28 files changed, 226 insertions(+), 131 deletions(-) create mode 100644 server/src/metadata/utils/create-custom-column-name.util.ts diff --git a/server/src/metadata/field-metadata/field-metadata.service.ts b/server/src/metadata/field-metadata/field-metadata.service.ts index 574fb494a..0fd4c7d66 100644 --- a/server/src/metadata/field-metadata/field-metadata.service.ts +++ b/server/src/metadata/field-metadata/field-metadata.service.ts @@ -7,7 +7,7 @@ import { import { InjectRepository } from '@nestjs/typeorm'; import { v4 as uuidV4 } from 'uuid'; -import { Repository } from 'typeorm'; +import { FindOneOptions, Repository } from 'typeorm'; import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { WorkspaceMigrationRunnerService } from 'src/workspace/workspace-migration-runner/workspace-migration-runner.service'; @@ -47,8 +47,12 @@ export class FieldMetadataService extends TypeOrmQueryService { const objectMetadata = await this.objectMetadataService.findOneWithinWorkspace( - record.objectMetadataId, record.workspaceId, + { + where: { + id: record.objectMetadataId, + }, + }, ); if (!objectMetadata) { @@ -156,8 +160,12 @@ export class FieldMetadataService extends TypeOrmQueryService, ) { return this.fieldMetadataRepository.findOne({ - where: { id: fieldMetadataId, workspaceId }, + ...options, + where: { + ...options.where, + workspaceId, + }, }); } diff --git a/server/src/metadata/field-metadata/hooks/before-delete-one-field.hook.ts b/server/src/metadata/field-metadata/hooks/before-delete-one-field.hook.ts index e7beb1ef4..1e3ae4dce 100644 --- a/server/src/metadata/field-metadata/hooks/before-delete-one-field.hook.ts +++ b/server/src/metadata/field-metadata/hooks/before-delete-one-field.hook.ts @@ -27,10 +27,11 @@ export class BeforeDeleteOneField implements BeforeDeleteOneHook { } const fieldMetadata = - await this.fieldMetadataService.findOneWithinWorkspace( - instance.id.toString(), - workspaceId, - ); + await this.fieldMetadataService.findOneWithinWorkspace(workspaceId, { + where: { + id: instance.id.toString(), + }, + }); if (!fieldMetadata) { throw new BadRequestException('Field does not exist'); diff --git a/server/src/metadata/field-metadata/hooks/before-update-one-field.hook.ts b/server/src/metadata/field-metadata/hooks/before-update-one-field.hook.ts index d2d39cafe..8efe56f3a 100644 --- a/server/src/metadata/field-metadata/hooks/before-update-one-field.hook.ts +++ b/server/src/metadata/field-metadata/hooks/before-update-one-field.hook.ts @@ -31,10 +31,11 @@ export class BeforeUpdateOneField } const fieldMetadata = - await this.fieldMetadataService.findOneWithinWorkspace( - instance.id.toString(), - workspaceId, - ); + await this.fieldMetadataService.findOneWithinWorkspace(workspaceId, { + where: { + id: instance.id.toString(), + }, + }); if (!fieldMetadata) { throw new BadRequestException('Field does not exist'); diff --git a/server/src/metadata/field-metadata/interfaces/field-metadata.interface.ts b/server/src/metadata/field-metadata/interfaces/field-metadata.interface.ts index 23e01227b..80413a6a8 100644 --- a/server/src/metadata/field-metadata/interfaces/field-metadata.interface.ts +++ b/server/src/metadata/field-metadata/interfaces/field-metadata.interface.ts @@ -16,6 +16,7 @@ export interface FieldMetadataInterface< defaultValue?: FieldMetadataDefaultValue; options?: FieldMetadataOptions; objectMetadataId: string; + workspaceId?: string; description?: string; isNullable?: boolean; fromRelationMetadata?: RelationMetadataEntity; diff --git a/server/src/metadata/field-metadata/utils/generate-target-column-map.util.ts b/server/src/metadata/field-metadata/utils/generate-target-column-map.util.ts index 5822e5c2d..69ddb21d0 100644 --- a/server/src/metadata/field-metadata/utils/generate-target-column-map.util.ts +++ b/server/src/metadata/field-metadata/utils/generate-target-column-map.util.ts @@ -3,6 +3,7 @@ import { BadRequestException } from '@nestjs/common'; import { FieldMetadataTargetColumnMap } from 'src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; +import { createCustomColumnName } from 'src/metadata/utils/create-custom-column-name.util'; /** * Generate a target column map for a given type, this is used to map the field to the correct column(s) in the database. @@ -16,7 +17,9 @@ export function generateTargetColumnMap( isCustomField: boolean, fieldName: string, ): FieldMetadataTargetColumnMap { - const columnName = isCustomField ? `_${fieldName}` : fieldName; + const columnName = isCustomField + ? createCustomColumnName(fieldName) + : fieldName; switch (type) { case FieldMetadataType.UUID: diff --git a/server/src/metadata/object-metadata/hooks/before-delete-one-object.hook.ts b/server/src/metadata/object-metadata/hooks/before-delete-one-object.hook.ts index 643c4ab7c..69bbe7cf4 100644 --- a/server/src/metadata/object-metadata/hooks/before-delete-one-object.hook.ts +++ b/server/src/metadata/object-metadata/hooks/before-delete-one-object.hook.ts @@ -26,10 +26,11 @@ export class BeforeDeleteOneObject implements BeforeDeleteOneHook { } const objectMetadata = - await this.objectMetadataService.findOneWithinWorkspace( - instance.id.toString(), - workspaceId, - ); + await this.objectMetadataService.findOneWithinWorkspace(workspaceId, { + where: { + id: instance.id.toString(), + }, + }); if (!objectMetadata) { throw new BadRequestException('Object does not exist'); diff --git a/server/src/metadata/object-metadata/hooks/before-update-one-object.hook.ts b/server/src/metadata/object-metadata/hooks/before-update-one-object.hook.ts index a6e89c02e..e6fd71aa9 100644 --- a/server/src/metadata/object-metadata/hooks/before-update-one-object.hook.ts +++ b/server/src/metadata/object-metadata/hooks/before-update-one-object.hook.ts @@ -39,10 +39,11 @@ export class BeforeUpdateOneObject } const objectMetadata = - await this.objectMetadataService.findOneWithinWorkspace( - instance.id.toString(), - workspaceId, - ); + await this.objectMetadataService.findOneWithinWorkspace(workspaceId, { + where: { + id: instance.id.toString(), + }, + }); if (!objectMetadata) { throw new BadRequestException('Object does not exist'); diff --git a/server/src/metadata/object-metadata/object-metadata.service.ts b/server/src/metadata/object-metadata/object-metadata.service.ts index 5597ce3fc..84a1a8e02 100644 --- a/server/src/metadata/object-metadata/object-metadata.service.ts +++ b/server/src/metadata/object-metadata/object-metadata.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { Equal, In, Repository } from 'typeorm'; +import { FindManyOptions, FindOneOptions, Repository } from 'typeorm'; import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { WorkspaceMigrationService } from 'src/metadata/workspace-migration/workspace-migration.service'; @@ -21,6 +21,7 @@ import { RelationMetadataEntity, RelationMetadataType, } from 'src/metadata/relation-metadata/relation-metadata.entity'; +import { createCustomColumnName } from 'src/metadata/utils/create-custom-column-name.util'; import { ObjectMetadataEntity } from './object-metadata.entity'; @@ -63,7 +64,7 @@ export class ObjectMetadataService extends TypeOrmQueryService, + ): Promise { + return this.objectMetadataRepository.findOne({ + ...options, + where: { + ...options.where, + workspaceId, + }, relations: [ 'fields', 'fields.fromRelationMetadata', - 'fields.fromRelationMetadata.fromObjectMetadata', - 'fields.fromRelationMetadata.toObjectMetadata', - 'fields.fromRelationMetadata.toObjectMetadata.fields', 'fields.toRelationMetadata', - 'fields.toRelationMetadata.fromObjectMetadata', - 'fields.toRelationMetadata.fromObjectMetadata.fields', - 'fields.toRelationMetadata.toObjectMetadata', ], }); } - public async findOneWithinWorkspace( - objectMetadataId: string, - workspaceId: string, - ) { - return this.objectMetadataRepository.findOne({ - where: { id: objectMetadataId, workspaceId }, - }); - } - public async findManyWithinWorkspace( - objectMetadataIds: string[], workspaceId: string, + options?: FindManyOptions, ) { - return this.objectMetadataRepository.findBy({ - id: In(objectMetadataIds), - workspaceId: Equal(workspaceId), + return this.objectMetadataRepository.find({ + ...options, + where: { + ...options?.where, + workspaceId, + }, + relations: [ + 'fields', + 'fields.fromRelationMetadata', + 'fields.toRelationMetadata', + ], }); } diff --git a/server/src/metadata/relation-metadata/hooks/before-delete-one-field.hook.ts b/server/src/metadata/relation-metadata/hooks/before-delete-one-field.hook.ts index 6b62f6db3..457796aed 100644 --- a/server/src/metadata/relation-metadata/hooks/before-delete-one-field.hook.ts +++ b/server/src/metadata/relation-metadata/hooks/before-delete-one-field.hook.ts @@ -26,10 +26,11 @@ export class BeforeDeleteOneRelation implements BeforeDeleteOneHook { } const relationMetadata = - await this.relationMetadataService.findOneWithinWorkspace( - instance.id.toString(), - workspaceId, - ); + await this.relationMetadataService.findOneWithinWorkspace(workspaceId, { + where: { + id: instance.id.toString(), + }, + }); if (!relationMetadata) { throw new BadRequestException('Relation does not exist'); diff --git a/server/src/metadata/relation-metadata/relation-metadata.service.ts b/server/src/metadata/relation-metadata/relation-metadata.service.ts index 7df62eedb..51be1bda6 100644 --- a/server/src/metadata/relation-metadata/relation-metadata.service.ts +++ b/server/src/metadata/relation-metadata/relation-metadata.service.ts @@ -6,7 +6,7 @@ import { import { InjectRepository } from '@nestjs/typeorm'; import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; -import { Repository } from 'typeorm'; +import { FindOneOptions, In, Repository } from 'typeorm'; import camelCase from 'lodash.camelcase'; import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service'; @@ -16,6 +16,8 @@ import { WorkspaceMigrationRunnerService } from 'src/workspace/workspace-migrati import { WorkspaceMigrationService } from 'src/metadata/workspace-migration/workspace-migration.service'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; import { WorkspaceMigrationColumnActionType } from 'src/metadata/workspace-migration/workspace-migration.entity'; +import { ObjectMetadataEntity } from 'src/metadata/object-metadata/object-metadata.entity'; +import { createCustomColumnName } from 'src/metadata/utils/create-custom-column-name.util'; import { RelationMetadataEntity, @@ -85,14 +87,18 @@ export class RelationMetadataService extends TypeOrmQueryService { acc[curr.id] = curr; return acc; - }, {}); + }, {} as { [key: string]: ObjectMetadataEntity }); if ( objectMetadataMap[record.fromObjectMetadataId] === undefined || @@ -103,7 +109,11 @@ export class RelationMetadataService extends TypeOrmQueryService, ) { return this.relationMetadataRepository.findOne({ - where: { id: relationMetadataId, workspaceId }, + ...options, + where: { + ...options.where, + workspaceId, + }, relations: ['fromFieldMetadata', 'toFieldMetadata'], }); } diff --git a/server/src/metadata/utils/create-custom-column-name.util.ts b/server/src/metadata/utils/create-custom-column-name.util.ts new file mode 100644 index 000000000..2eb4674e4 --- /dev/null +++ b/server/src/metadata/utils/create-custom-column-name.util.ts @@ -0,0 +1,3 @@ +export const createCustomColumnName = (name: string) => { + return `_${name}`; +}; diff --git a/server/src/workspace/workspace-query-builder/factories/create-many-query.factory.ts b/server/src/workspace/workspace-query-builder/factories/create-many-query.factory.ts index 5ef332b55..54d3d3017 100644 --- a/server/src/workspace/workspace-query-builder/factories/create-many-query.factory.ts +++ b/server/src/workspace/workspace-query-builder/factories/create-many-query.factory.ts @@ -20,11 +20,11 @@ export class CreateManyQueryFactory { private readonly argsAliasFactory: ArgsAliasFactory, ) {} - create( + async create( args: CreateManyResolverArgs, options: WorkspaceQueryBuilderOptions, ) { - const fieldsString = this.fieldsStringFactory.create( + const fieldsString = await this.fieldsStringFactory.create( options.info, options.fieldMetadataCollection, ); diff --git a/server/src/workspace/workspace-query-builder/factories/delete-many-query.factory.ts b/server/src/workspace/workspace-query-builder/factories/delete-many-query.factory.ts index 276b73e5f..d51a078bb 100644 --- a/server/src/workspace/workspace-query-builder/factories/delete-many-query.factory.ts +++ b/server/src/workspace/workspace-query-builder/factories/delete-many-query.factory.ts @@ -11,8 +11,11 @@ import { FieldsStringFactory } from './fields-string.factory'; export class DeleteManyQueryFactory { constructor(private readonly fieldsStringFactory: FieldsStringFactory) {} - create(args: DeleteManyResolverArgs, options: WorkspaceQueryBuilderOptions) { - const fieldsString = this.fieldsStringFactory.create( + async create( + args: DeleteManyResolverArgs, + options: WorkspaceQueryBuilderOptions, + ) { + const fieldsString = await this.fieldsStringFactory.create( options.info, options.fieldMetadataCollection, ); diff --git a/server/src/workspace/workspace-query-builder/factories/delete-one-query.factory.ts b/server/src/workspace/workspace-query-builder/factories/delete-one-query.factory.ts index 799de88d9..e55531dbd 100644 --- a/server/src/workspace/workspace-query-builder/factories/delete-one-query.factory.ts +++ b/server/src/workspace/workspace-query-builder/factories/delete-one-query.factory.ts @@ -11,8 +11,11 @@ export class DeleteOneQueryFactory { constructor(private readonly fieldsStringFactory: FieldsStringFactory) {} - create(args: DeleteOneResolverArgs, options: WorkspaceQueryBuilderOptions) { - const fieldsString = this.fieldsStringFactory.create( + async create( + args: DeleteOneResolverArgs, + options: WorkspaceQueryBuilderOptions, + ) { + const fieldsString = await this.fieldsStringFactory.create( options.info, options.fieldMetadataCollection, ); diff --git a/server/src/workspace/workspace-query-builder/factories/fields-string.factory.ts b/server/src/workspace/workspace-query-builder/factories/fields-string.factory.ts index 5cfffa686..8faa3dc5f 100644 --- a/server/src/workspace/workspace-query-builder/factories/fields-string.factory.ts +++ b/server/src/workspace/workspace-query-builder/factories/fields-string.factory.ts @@ -23,7 +23,7 @@ export class FieldsStringFactory { create( info: GraphQLResolveInfo, fieldMetadataCollection: FieldMetadataInterface[], - ) { + ): Promise { const selectedFields: Record = graphqlFields(info); return this.createFieldsStringRecursive( @@ -33,12 +33,12 @@ export class FieldsStringFactory { ); } - createFieldsStringRecursive( + async createFieldsStringRecursive( info: GraphQLResolveInfo, selectedFields: Record, fieldMetadataCollection: FieldMetadataInterface[], accumulator = '', - ): string { + ): Promise { const fieldMetadataMap = new Map( fieldMetadataCollection.map((metadata) => [metadata.name, metadata]), ); @@ -54,7 +54,7 @@ export class FieldsStringFactory { // If the field is a relation field, we need to create a special alias if (isRelationFieldMetadataType(fieldMetadata.type)) { - const alias = this.relationFieldAliasFactory.create( + const alias = await this.relationFieldAliasFactory.create( fieldKey, fieldValue, fieldMetadata, @@ -80,7 +80,7 @@ export class FieldsStringFactory { !isEmpty(fieldValue) ) { accumulator += `${fieldKey} {\n`; - accumulator = this.createFieldsStringRecursive( + accumulator = await this.createFieldsStringRecursive( info, fieldValue, fieldMetadataCollection, diff --git a/server/src/workspace/workspace-query-builder/factories/find-many-query.factory.ts b/server/src/workspace/workspace-query-builder/factories/find-many-query.factory.ts index 8554a329c..c3f19c87c 100644 --- a/server/src/workspace/workspace-query-builder/factories/find-many-query.factory.ts +++ b/server/src/workspace/workspace-query-builder/factories/find-many-query.factory.ts @@ -19,14 +19,14 @@ export class FindManyQueryFactory { private readonly argsStringFactory: ArgsStringFactory, ) {} - create< + async create< Filter extends RecordFilter = RecordFilter, OrderBy extends RecordOrderBy = RecordOrderBy, >( args: FindManyResolverArgs, options: WorkspaceQueryBuilderOptions, ) { - const fieldsString = this.fieldsStringFactory.create( + const fieldsString = await this.fieldsStringFactory.create( options.info, options.fieldMetadataCollection, ); diff --git a/server/src/workspace/workspace-query-builder/factories/find-one-query.factory.ts b/server/src/workspace/workspace-query-builder/factories/find-one-query.factory.ts index 98f27fb06..94b07992e 100644 --- a/server/src/workspace/workspace-query-builder/factories/find-one-query.factory.ts +++ b/server/src/workspace/workspace-query-builder/factories/find-one-query.factory.ts @@ -16,11 +16,11 @@ export class FindOneQueryFactory { private readonly argsStringFactory: ArgsStringFactory, ) {} - create( + async create( args: FindOneResolverArgs, options: WorkspaceQueryBuilderOptions, ) { - const fieldsString = this.fieldsStringFactory.create( + const fieldsString = await this.fieldsStringFactory.create( options.info, options.fieldMetadataCollection, ); diff --git a/server/src/workspace/workspace-query-builder/factories/relation-field-alias.factory.ts b/server/src/workspace/workspace-query-builder/factories/relation-field-alias.factory.ts index 79e6c9266..d17e42abc 100644 --- a/server/src/workspace/workspace-query-builder/factories/relation-field-alias.factory.ts +++ b/server/src/workspace/workspace-query-builder/factories/relation-field-alias.factory.ts @@ -11,6 +11,7 @@ import { RelationDirection, } from 'src/workspace/utils/deduce-relation-direction.util'; import { getFieldArgumentsByKey } from 'src/workspace/workspace-query-builder/utils/get-field-arguments-by-key.util'; +import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service'; import { FieldsStringFactory } from './fields-string.factory'; import { ArgsStringFactory } from './args-string.factory'; @@ -23,6 +24,7 @@ export class RelationFieldAliasFactory { @Inject(forwardRef(() => FieldsStringFactory)) private readonly fieldsStringFactory: FieldsStringFactory, private readonly argsStringFactory: ArgsStringFactory, + private readonly objectMetadataService: ObjectMetadataService, ) {} create( @@ -30,7 +32,7 @@ export class RelationFieldAliasFactory { fieldValue: any, fieldMetadata: FieldMetadataInterface, info: GraphQLResolveInfo, - ) { + ): Promise { if (!isRelationFieldMetadataType(fieldMetadata.type)) { throw new Error(`Field ${fieldMetadata.name} is not a relation field`); } @@ -38,12 +40,12 @@ export class RelationFieldAliasFactory { return this.createRelationAlias(fieldKey, fieldValue, fieldMetadata, info); } - private createRelationAlias( + private async createRelationAlias( fieldKey: string, fieldValue: any, fieldMetadata: FieldMetadataInterface, info: GraphQLResolveInfo, - ) { + ): Promise { const relationMetadata = fieldMetadata.fromRelationMetadata ?? fieldMetadata.toRelationMetadata; @@ -53,14 +55,36 @@ export class RelationFieldAliasFactory { ); } + if (!fieldMetadata.workspaceId) { + throw new Error( + `Workspace id not found for field ${fieldMetadata.name} in object metadata ${fieldMetadata.objectMetadataId}`, + ); + } + const relationDirection = deduceRelationDirection( fieldMetadata.objectMetadataId, relationMetadata, ); + // Retrieve the referenced object metadata based on the relation direction + // Mandatory to handle n+n relations const referencedObjectMetadata = - relationDirection == RelationDirection.TO - ? relationMetadata.fromObjectMetadata - : relationMetadata.toObjectMetadata; + await this.objectMetadataService.findOneWithinWorkspace( + fieldMetadata.workspaceId, + { + where: { + id: + relationDirection == RelationDirection.TO + ? relationMetadata.fromObjectMetadataId + : relationMetadata.toObjectMetadataId, + }, + }, + ); + + if (!referencedObjectMetadata) { + throw new Error( + `Referenced object metadata not found for relation ${relationMetadata.id}`, + ); + } // If it's a relation destination is of kind MANY, we need to add the collection suffix and extract the args if ( @@ -70,21 +94,26 @@ export class RelationFieldAliasFactory { const args = getFieldArgumentsByKey(info, fieldKey); const argsString = this.argsStringFactory.create( args, - relationMetadata.toObjectMetadata.fields ?? [], + referencedObjectMetadata.fields ?? [], ); + const fieldsString = + await this.fieldsStringFactory.createFieldsStringRecursive( + info, + fieldValue, + referencedObjectMetadata.fields ?? [], + ); + return ` ${fieldKey}: ${referencedObjectMetadata.targetTableName}Collection${ argsString ? `(${argsString})` : '' } { - ${this.fieldsStringFactory.createFieldsStringRecursive( - info, - fieldValue, - relationMetadata.toObjectMetadata.fields ?? [], - )} + ${fieldsString} } `; } - let relationAlias = fieldMetadata.isCustom ? `_${fieldKey}` : fieldKey; + let relationAlias = fieldMetadata.isCustom + ? `${fieldKey}: ${fieldMetadata.targetColumnMap.value}` + : fieldKey; // For one to one relations, pg_graphql use the targetTableName on the side that is not storing the foreign key // so we need to alias it to the field key @@ -94,15 +123,17 @@ export class RelationFieldAliasFactory { ) { relationAlias = `${fieldKey}: ${referencedObjectMetadata.targetTableName}`; } + const fieldsString = + await this.fieldsStringFactory.createFieldsStringRecursive( + info, + fieldValue, + referencedObjectMetadata.fields ?? [], + ); // Otherwise it means it's a relation destination is of kind ONE return ` ${relationAlias} { - ${this.fieldsStringFactory.createFieldsStringRecursive( - info, - fieldValue, - referencedObjectMetadata.fields ?? [], - )} + ${fieldsString} } `; } diff --git a/server/src/workspace/workspace-query-builder/factories/update-many-query.factory.ts b/server/src/workspace/workspace-query-builder/factories/update-many-query.factory.ts index 46d963607..148f77a54 100644 --- a/server/src/workspace/workspace-query-builder/factories/update-many-query.factory.ts +++ b/server/src/workspace/workspace-query-builder/factories/update-many-query.factory.ts @@ -18,14 +18,14 @@ export class UpdateManyQueryFactory { private readonly argsAliasFactory: ArgsAliasFactory, ) {} - create< + async create< Record extends IRecord = IRecord, Filter extends RecordFilter = RecordFilter, >( args: UpdateManyResolverArgs, options: WorkspaceQueryBuilderOptions, ) { - const fieldsString = this.fieldsStringFactory.create( + const fieldsString = await this.fieldsStringFactory.create( options.info, options.fieldMetadataCollection, ); diff --git a/server/src/workspace/workspace-query-builder/factories/update-one-query.factory.ts b/server/src/workspace/workspace-query-builder/factories/update-one-query.factory.ts index eb43812a9..bf52cdabf 100644 --- a/server/src/workspace/workspace-query-builder/factories/update-one-query.factory.ts +++ b/server/src/workspace/workspace-query-builder/factories/update-one-query.factory.ts @@ -18,11 +18,11 @@ export class UpdateOneQueryFactory { private readonly argsAliasFactory: ArgsAliasFactory, ) {} - create( + async create( args: UpdateOneResolverArgs, options: WorkspaceQueryBuilderOptions, ) { - const fieldsString = this.fieldsStringFactory.create( + const fieldsString = await this.fieldsStringFactory.create( options.info, options.fieldMetadataCollection, ); diff --git a/server/src/workspace/workspace-query-builder/workspace-query-builder.factory.ts b/server/src/workspace/workspace-query-builder/workspace-query-builder.factory.ts index 0f706edbf..1d76e9970 100644 --- a/server/src/workspace/workspace-query-builder/workspace-query-builder.factory.ts +++ b/server/src/workspace/workspace-query-builder/workspace-query-builder.factory.ts @@ -44,35 +44,35 @@ export class WorkspaceQueryBuilderFactory { >( args: FindManyResolverArgs, options: WorkspaceQueryBuilderOptions, - ): string { + ): Promise { return this.findManyQueryFactory.create(args, options); } findOne( args: FindOneResolverArgs, options: WorkspaceQueryBuilderOptions, - ): string { + ): Promise { return this.findOneQueryFactory.create(args, options); } createMany( args: CreateManyResolverArgs, options: WorkspaceQueryBuilderOptions, - ): string { + ): Promise { return this.createManyQueryFactory.create(args, options); } updateOne( initialArgs: UpdateOneResolverArgs, options: WorkspaceQueryBuilderOptions, - ): string { + ): Promise { return this.updateOneQueryFactory.create(initialArgs, options); } deleteOne( args: DeleteOneResolverArgs, options: WorkspaceQueryBuilderOptions, - ): string { + ): Promise { return this.deleteOneQueryFactory.create(args, options); } @@ -82,14 +82,14 @@ export class WorkspaceQueryBuilderFactory { >( args: UpdateManyResolverArgs, options: WorkspaceQueryBuilderOptions, - ): string { + ): Promise { return this.updateManyQueryFactory.create(args, options); } deleteMany( args: DeleteManyResolverArgs, options: WorkspaceQueryBuilderOptions, - ): string { + ): Promise { return this.deleteManyQueryFactory.create(args, options); } } diff --git a/server/src/workspace/workspace-query-builder/workspace-query-builder.module.ts b/server/src/workspace/workspace-query-builder/workspace-query-builder.module.ts index 5edb49373..7b25351a7 100644 --- a/server/src/workspace/workspace-query-builder/workspace-query-builder.module.ts +++ b/server/src/workspace/workspace-query-builder/workspace-query-builder.module.ts @@ -1,11 +1,13 @@ import { Module } from '@nestjs/common'; +import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module'; + import { WorkspaceQueryBuilderFactory } from './workspace-query-builder.factory'; import { workspaceQueryBuilderFactories } from './factories/factories'; @Module({ - imports: [], + imports: [ObjectMetadataModule], providers: [...workspaceQueryBuilderFactories, WorkspaceQueryBuilderFactory], exports: [WorkspaceQueryBuilderFactory], }) diff --git a/server/src/workspace/workspace-query-runner/workspace-query-runner.service.ts b/server/src/workspace/workspace-query-runner/workspace-query-runner.service.ts index e0956029b..3b40a839c 100644 --- a/server/src/workspace/workspace-query-runner/workspace-query-runner.service.ts +++ b/server/src/workspace/workspace-query-runner/workspace-query-runner.service.ts @@ -45,7 +45,10 @@ export class WorkspaceQueryRunnerService { options: WorkspaceQueryRunnerOptions, ): Promise | undefined> { const { workspaceId, targetTableName } = options; - const query = this.workspaceQueryBuilderFactory.findMany(args, options); + const query = await this.workspaceQueryBuilderFactory.findMany( + args, + options, + ); const result = await this.execute(query, workspaceId); return this.parseResult>(result, targetTableName, ''); @@ -62,7 +65,10 @@ export class WorkspaceQueryRunnerService { throw new BadRequestException('Missing filter argument'); } const { workspaceId, targetTableName } = options; - const query = this.workspaceQueryBuilderFactory.findOne(args, options); + const query = await this.workspaceQueryBuilderFactory.findOne( + args, + options, + ); const result = await this.execute(query, workspaceId); const parsedResult = this.parseResult>( result, @@ -78,7 +84,10 @@ export class WorkspaceQueryRunnerService { options: WorkspaceQueryRunnerOptions, ): Promise { const { workspaceId, targetTableName } = options; - const query = this.workspaceQueryBuilderFactory.createMany(args, options); + const query = await this.workspaceQueryBuilderFactory.createMany( + args, + options, + ); const result = await this.execute(query, workspaceId); return this.parseResult>( @@ -102,9 +111,10 @@ export class WorkspaceQueryRunnerService { options: WorkspaceQueryRunnerOptions, ): Promise { const { workspaceId, targetTableName } = options; - - const query = this.workspaceQueryBuilderFactory.updateOne(args, options); - + const query = await this.workspaceQueryBuilderFactory.updateOne( + args, + options, + ); const result = await this.execute(query, workspaceId); return this.parseResult>( @@ -119,7 +129,10 @@ export class WorkspaceQueryRunnerService { options: WorkspaceQueryRunnerOptions, ): Promise { const { workspaceId, targetTableName } = options; - const query = this.workspaceQueryBuilderFactory.deleteOne(args, options); + const query = await this.workspaceQueryBuilderFactory.deleteOne( + args, + options, + ); const result = await this.execute(query, workspaceId); return this.parseResult>( @@ -134,9 +147,10 @@ export class WorkspaceQueryRunnerService { options: WorkspaceQueryRunnerOptions, ): Promise { const { workspaceId, targetTableName } = options; - - const query = this.workspaceQueryBuilderFactory.updateMany(args, options); - + const query = await this.workspaceQueryBuilderFactory.updateMany( + args, + options, + ); const result = await this.execute(query, workspaceId); return this.parseResult>( @@ -154,9 +168,10 @@ export class WorkspaceQueryRunnerService { options: WorkspaceQueryRunnerOptions, ): Promise { const { workspaceId, targetTableName } = options; - - const query = this.workspaceQueryBuilderFactory.deleteMany(args, options); - + const query = await this.workspaceQueryBuilderFactory.deleteMany( + args, + options, + ); const result = await this.execute(query, workspaceId); return this.parseResult>( diff --git a/server/src/workspace/workspace-schema-builder/factories/args.factory.ts b/server/src/workspace/workspace-schema-builder/factories/args.factory.ts index d3fdb87f1..646f31ce0 100644 --- a/server/src/workspace/workspace-schema-builder/factories/args.factory.ts +++ b/server/src/workspace/workspace-schema-builder/factories/args.factory.ts @@ -18,7 +18,7 @@ export class ArgsFactory { ) {} public create( - { args, objectMetadata }: ArgsMetadata, + { args, objectMetadataId }: ArgsMetadata, options: WorkspaceBuildSchemaOptions, ): GraphQLFieldConfigArgumentMap { const fieldConfigMap: GraphQLFieldConfigArgumentMap = {}; @@ -65,21 +65,21 @@ export class ArgsFactory { // Argument is an input type if (arg.kind) { const inputType = this.typeDefinitionsStorage.getInputTypeByKey( - objectMetadata.id, + objectMetadataId, arg.kind, ); if (!inputType) { this.logger.error( - `Could not find a GraphQL input type for ${objectMetadata.id}`, + `Could not find a GraphQL input type for ${objectMetadataId}`, { - objectMetadata, + objectMetadataId, options, }, ); throw new Error( - `Could not find a GraphQL input type for ${objectMetadata.id}`, + `Could not find a GraphQL input type for ${objectMetadataId}`, ); } diff --git a/server/src/workspace/workspace-schema-builder/factories/extend-object-type-definition.factory.ts b/server/src/workspace/workspace-schema-builder/factories/extend-object-type-definition.factory.ts index d4c852e44..60b984739 100644 --- a/server/src/workspace/workspace-schema-builder/factories/extend-object-type-definition.factory.ts +++ b/server/src/workspace/workspace-schema-builder/factories/extend-object-type-definition.factory.ts @@ -155,7 +155,7 @@ export class ExtendObjectTypeDefinitionFactory { argsType = this.argsFactory.create( { args, - objectMetadata: relationMetadata.toObjectMetadata, + objectMetadataId: relationMetadata.toObjectMetadataId, }, options, ); diff --git a/server/src/workspace/workspace-schema-builder/factories/root-type.factory.ts b/server/src/workspace/workspace-schema-builder/factories/root-type.factory.ts index 88927e84a..b15e1e7b3 100644 --- a/server/src/workspace/workspace-schema-builder/factories/root-type.factory.ts +++ b/server/src/workspace/workspace-schema-builder/factories/root-type.factory.ts @@ -81,7 +81,7 @@ export class RootTypeFactory { const argsType = this.argsFactory.create( { args, - objectMetadata, + objectMetadataId: objectMetadata.id, }, options, ); diff --git a/server/src/workspace/workspace-schema-builder/interfaces/param-metadata.interface.ts b/server/src/workspace/workspace-schema-builder/interfaces/param-metadata.interface.ts index 2b9f94eb3..12a1ac181 100644 --- a/server/src/workspace/workspace-schema-builder/interfaces/param-metadata.interface.ts +++ b/server/src/workspace/workspace-schema-builder/interfaces/param-metadata.interface.ts @@ -1,5 +1,3 @@ -import { ObjectMetadataInterface } from 'src/metadata/field-metadata/interfaces/object-metadata.interface'; - import { InputTypeDefinitionKind } from 'src/workspace/workspace-schema-builder/factories/input-type-definition.factory'; import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity'; @@ -15,5 +13,5 @@ export interface ArgsMetadata { args: { [key: string]: ArgMetadata; }; - objectMetadata: ObjectMetadataInterface; + objectMetadataId: string; } diff --git a/server/src/workspace/workspace.factory.ts b/server/src/workspace/workspace.factory.ts index fd3aec1a3..88e1b0f79 100644 --- a/server/src/workspace/workspace.factory.ts +++ b/server/src/workspace/workspace.factory.ts @@ -51,9 +51,7 @@ export class WorkspaceFactory { // If object metadata is not cached, get it from the database if (!objectMetadataCollection) { objectMetadataCollection = - await this.objectMetadataService.getObjectMetadataFromWorkspaceId( - workspaceId, - ); + await this.objectMetadataService.findManyWithinWorkspace(workspaceId); await this.workspaceSchemaStorageService.setObjectMetadata( workspaceId,