Prechádzať zdrojové kódy

fix(core): Fix loading multiple customField relations (#2566)

fixes #2555
Jonas Osburg 2 rokov pred
rodič
commit
99e04d1d0b

+ 42 - 3
packages/core/e2e/fixtures/test-plugins/list-query-plugin.ts

@@ -39,9 +39,25 @@ export class CustomFieldRelationTestEntity extends VendureEntity {
     parent: Relation<TestEntity>;
 }
 
+@Entity()
+export class CustomFieldOtherRelationTestEntity extends VendureEntity {
+    constructor(input: Partial<CustomFieldOtherRelationTestEntity>) {
+        super(input);
+    }
+
+    @Column()
+    data: string;
+
+    @ManyToOne(() => TestEntity)
+    parent: Relation<TestEntity>;
+}
+
 class TestEntityCustomFields {
     @OneToMany(() => CustomFieldRelationTestEntity, child => child.parent)
     relation: Relation<CustomFieldRelationTestEntity[]>;
+
+    @OneToMany(() => CustomFieldOtherRelationTestEntity, child => child.parent)
+    otherRelation: Relation<CustomFieldOtherRelationTestEntity[]>;
 }
 
 @Entity()
@@ -143,7 +159,7 @@ export class TestEntityTranslation extends VendureEntity implements Translation<
     @ManyToOne(type => TestEntity, base => base.translations)
     base: TestEntity;
 
-    customFields: {};
+    customFields: never;
 }
 
 @Entity()
@@ -171,7 +187,12 @@ export class ListQueryResolver {
         return this.listQueryBuilder
             .build(TestEntity, args.options, {
                 ctx,
-                relations: ['orderRelation', 'orderRelation.customer', 'customFields.relation'],
+                relations: [
+                    'orderRelation',
+                    'orderRelation.customer',
+                    'customFields.relation',
+                    'customFields.otherRelation',
+                ],
                 customPropertyMap: {
                     customerLastName: 'orderRelation.customer.lastName',
                 },
@@ -222,8 +243,14 @@ const apiExtensions = gql`
         data: String!
     }
 
+    type CustomFieldOtherRelationTestEntity implements Node {
+        id: ID!
+        data: String!
+    }
+
     type TestEntityCustomFields {
         relation: [CustomFieldRelationTestEntity!]!
+        otherRelation: [CustomFieldOtherRelationTestEntity!]!
     }
 
     type TestEntity implements Node {
@@ -272,7 +299,13 @@ const apiExtensions = gql`
 
 @VendurePlugin({
     imports: [PluginCommonModule],
-    entities: [TestEntity, TestEntityPrice, TestEntityTranslation, CustomFieldRelationTestEntity],
+    entities: [
+        TestEntity,
+        TestEntityPrice,
+        TestEntityTranslation,
+        CustomFieldRelationTestEntity,
+        CustomFieldOtherRelationTestEntity,
+    ],
     adminApiExtensions: {
         schema: apiExtensions,
         resolvers: [ListQueryResolver],
@@ -409,6 +442,12 @@ export class ListQueryPlugin implements OnApplicationBootstrap {
                                 data: nestedContent.data,
                             }),
                         );
+                        await this.connection.getRepository(CustomFieldOtherRelationTestEntity).save(
+                            new CustomFieldOtherRelationTestEntity({
+                                parent: testEntity,
+                                data: nestedContent.data,
+                            }),
+                        );
                     }
                 }
             }

+ 42 - 0
packages/core/e2e/list-query-builder.e2e-spec.ts

@@ -1268,6 +1268,27 @@ describe('ListQueryBuilder', () => {
                 },
             ]);
         });
+
+        it('should resolve multiple relations in customFields successfully', async () => {
+            const { testEntities } = await shopClient.query(GET_LIST_WITH_MULTIPLE_CUSTOM_FIELD_RELATION, {
+                options: {
+                    filter: {
+                        label: { eq: 'A' },
+                    },
+                },
+            });
+
+            expect(testEntities.items).toEqual([
+                {
+                    id: 'T_1',
+                    label: 'A',
+                    customFields: {
+                        relation: [{ id: 'T_1', data: 'A' }],
+                        otherRelation: [{ id: 'T_1', data: 'A' }],
+                    },
+                },
+            ]);
+        });
     });
 });
 
@@ -1351,3 +1372,24 @@ const GET_LIST_WITH_CUSTOM_FIELD_RELATION = gql`
         }
     }
 `;
+
+const GET_LIST_WITH_MULTIPLE_CUSTOM_FIELD_RELATION = gql`
+    query GetTestWithMultipleCustomFieldRelation($options: TestEntityListOptions) {
+        testEntities(options: $options) {
+            items {
+                id
+                label
+                customFields {
+                    relation {
+                        id
+                        data
+                    }
+                    otherRelation {
+                        id
+                        data
+                    }
+                }
+            }
+        }
+    }
+`;

+ 10 - 3
packages/core/src/service/helpers/list-query-builder/list-query-builder.ts

@@ -493,14 +493,21 @@ export class ListQueryBuilder implements OnApplicationBootstrap {
                         loadEagerRelations: true,
                     } as FindManyOptions<T>)
                     .then(results =>
-                        results.map(r => ({ relation: relationPaths[0] as keyof T, entity: r })),
+                        results.map(r => ({
+                            relations: relationPaths[0].startsWith('customFields.')
+                                ? relationPaths
+                                : [relationPaths[0]],
+                            entity: r,
+                        })),
                     );
             }),
         ).then(all => all.flat());
         for (const entry of entitiesIdsWithRelations) {
             const finalEntity = entityMap.get(entry.entity.id);
-            if (finalEntity) {
-                this.assignDeep(entry.relation, entry.entity, finalEntity);
+            for (const relation of entry.relations) {
+                if (finalEntity) {
+                    this.assignDeep(relation, entry.entity, finalEntity);
+                }
             }
         }
         return Array.from(entityMap.values());