diff --git a/packages/core/types/src/dal/index.ts b/packages/core/types/src/dal/index.ts index fe9646a67c..aafe8fab74 100644 --- a/packages/core/types/src/dal/index.ts +++ b/packages/core/types/src/dal/index.ts @@ -51,6 +51,10 @@ export interface OptionsQuery { * Filters to apply on the retrieved items. */ filters?: Dictionary | string[] | boolean + /** + * Load strategy (e.g for mikro orm it accept select-in or joined) + */ + strategy?: 'select-in' | 'joined' | string & {} } /** diff --git a/packages/core/utils/src/dal/mikro-orm/mikro-orm-repository.ts b/packages/core/utils/src/dal/mikro-orm/mikro-orm-repository.ts index 02f59994f4..5210b1f16c 100644 --- a/packages/core/utils/src/dal/mikro-orm/mikro-orm-repository.ts +++ b/packages/core/utils/src/dal/mikro-orm/mikro-orm-repository.ts @@ -10,24 +10,22 @@ import { UpsertWithReplaceConfig, } from "@medusajs/types" import { + EntityClass, EntityManager, + EntityName, + EntityProperty, EntitySchema, + FilterQuery as MikroFilterQuery, + FindOptions as MikroOptions, LoadStrategy, ReferenceType, RequiredEntityData, } from "@mikro-orm/core" -import { - EntityClass, - EntityName, - EntityProperty, - FindOptions as MikroOptions, - FilterQuery as MikroFilterQuery, -} from "@mikro-orm/core" import { SqlEntityManager } from "@mikro-orm/postgresql" import { - MedusaError, arrayDifference, isString, + MedusaError, promiseAll, } from "../../common" import { buildQuery } from "../../modules-sdk/build-query" @@ -112,6 +110,40 @@ export class MikroOrmBaseRepository ) } + /** + * When using the select-in strategy, the populated fields are not selected by default unlike when using the joined strategy. + * This method will add the populated fields to the fields array if they are not already specifically selected. + * + * TODO: Revisit if this is still needed in v6 as it seems to be a workaround for a bug in v5 + * + * @param {FindOptions} findOptions + */ + static compensateRelationFieldsSelectionFromLoadStrategy({ + findOptions, + }: { + findOptions: DAL.FindOptions + }) { + const loadStrategy = findOptions?.options?.strategy + + if (loadStrategy !== LoadStrategy.SELECT_IN) { + return + } + + findOptions.options ??= {} + const populate = findOptions.options.populate ?? [] + const fields = findOptions.options.fields ?? [] + populate.forEach((populateRelation: string) => { + if ( + fields.some((field: string) => field.startsWith(populateRelation + ".")) + ) { + return + } + + // If there is no specific fields selected for the relation but the relation is populated, we select all fields + fields.push(populateRelation + ".*") + }) + } + create(data: unknown[], context?: Context): Promise { throw new Error("Method not implemented.") } @@ -317,7 +349,10 @@ export function mikroOrmBaseRepositoryFactory( await manager.nativeDelete(entity as EntityName, filters as any) } - async find(options?: DAL.FindOptions, context?: Context): Promise { + async find( + options: DAL.FindOptions = { where: {} }, + context?: Context + ): Promise { const manager = this.getActiveManager(context) const findOptions_ = { ...options } @@ -335,6 +370,10 @@ export function mikroOrmBaseRepositoryFactory( } } + MikroOrmBaseRepository.compensateRelationFieldsSelectionFromLoadStrategy({ + findOptions: findOptions_, + }) + return await manager.find( entity as EntityName, findOptions_.where as MikroFilterQuery, @@ -355,6 +394,10 @@ export function mikroOrmBaseRepositoryFactory( strategy: LoadStrategy.SELECT_IN, }) + MikroOrmBaseRepository.compensateRelationFieldsSelectionFromLoadStrategy({ + findOptions: findOptions_, + }) + return await manager.findAndCount( entity as EntityName, findOptions_.where as MikroFilterQuery,