1
0
Эх сурвалжийг харах

fix(core): Fix findOneInChannel with relations object

Fixes #2809
Michael Bromley 1 жил өмнө
parent
commit
b9eb7db653

+ 29 - 0
packages/core/src/connection/find-options-object-to-array.ts

@@ -0,0 +1,29 @@
+import { FindOneOptions } from 'typeorm';
+import { FindOptionsRelationByString } from 'typeorm/find-options/FindOptionsRelations';
+
+/**
+ * Some internal APIs depend on the TypeORM FindOptions `relations` property being a string array.
+ * This function converts the new-style FindOptionsRelations object to a string array.
+ */
+export function findOptionsObjectToArray<T>(
+    input: NonNullable<FindOneOptions['relations']>,
+    parentKey?: string,
+): FindOptionsRelationByString {
+    if (Array.isArray(input)) {
+        return input;
+    }
+    const keys = Object.keys(input);
+
+    return keys.reduce((acc: string[], key: string) => {
+        const value = input[key as any];
+        const path = parentKey ? `${parentKey}.${key}` : key;
+
+        acc.push(path); // Push parent key instead of path
+        if (typeof value === 'object' && value !== null) {
+            const subKeys = findOptionsObjectToArray(value, path);
+            acc.push(...subKeys);
+        }
+
+        return acc;
+    }, []);
+}

+ 6 - 3
packages/core/src/connection/transactional-connection.ts

@@ -5,8 +5,8 @@ import {
     DataSource,
     EntityManager,
     EntitySchema,
-    FindOneOptions,
     FindManyOptions,
+    FindOneOptions,
     ObjectLiteral,
     ObjectType,
     Repository,
@@ -21,6 +21,7 @@ import { ChannelAware, SoftDeletable } from '../common/types/common-types';
 import { VendureEntity } from '../entity/base/base.entity';
 import { joinTreeRelationsDynamically } from '../service/helpers/utils/tree-relations-qb-joiner';
 
+import { findOptionsObjectToArray } from './find-options-object-to-array';
 import { TransactionWrapper } from './transaction-wrapper';
 import { GetEntityOrThrowOptions } from './types';
 
@@ -278,11 +279,13 @@ export class TransactionalConnection {
     ) {
         const qb = this.getRepository(ctx, entity).createQueryBuilder('entity');
 
-        if (Array.isArray(options.relations) && options.relations.length > 0) {
+        if (options.relations) {
             const joinedRelations = joinTreeRelationsDynamically(qb, entity, options.relations);
             // Remove any relations which are related to the 'collection' tree, as these are handled separately
             // to avoid duplicate joins.
-            options.relations = options.relations.filter(relationPath => !joinedRelations.has(relationPath));
+            options.relations = findOptionsObjectToArray(options.relations).filter(
+                relationPath => !joinedRelations.has(relationPath),
+            );
         }
         qb.setFindOptions({
             relationLoadStrategy: 'query', // default to query strategy for maximum performance

+ 7 - 4
packages/core/src/service/helpers/utils/tree-relations-qb-joiner.ts

@@ -1,6 +1,8 @@
-import { EntityMetadata, SelectQueryBuilder } from 'typeorm';
+import { EntityMetadata, FindOneOptions, SelectQueryBuilder } from 'typeorm';
 import { EntityTarget } from 'typeorm/common/EntityTarget';
+import { FindOptionsRelationByString, FindOptionsRelations } from 'typeorm/find-options/FindOptionsRelations';
 
+import { findOptionsObjectToArray } from '../../../connection/find-options-object-to-array';
 import { VendureEntity } from '../../../entity';
 
 /**
@@ -55,11 +57,12 @@ function isTreeEntityMetadata(metadata: EntityMetadata): boolean {
 export function joinTreeRelationsDynamically<T extends VendureEntity>(
     qb: SelectQueryBuilder<T>,
     entity: EntityTarget<T>,
-    requestedRelations: string[] = [],
+    requestedRelations: FindOneOptions['relations'] = {},
     maxEagerDepth: number = 1,
 ): Map<string, string> {
     const joinedRelations = new Map<string, string>();
-    if (!requestedRelations.length) {
+    const relationsArray = findOptionsObjectToArray(requestedRelations);
+    if (!relationsArray.length) {
         return joinedRelations;
     }
 
@@ -147,7 +150,7 @@ export function joinTreeRelationsDynamically<T extends VendureEntity>(
         }
     };
 
-    requestedRelations.forEach(relationPath => {
+    relationsArray.forEach(relationPath => {
         if (!joinedRelations.has(relationPath)) {
             processRelation(sourceMetadata, sourceMetadataIsTree, relationPath, qb.alias);
         }