diff --git a/packages/medusa/src/repositories/cart.ts b/packages/medusa/src/repositories/cart.ts index 6955ad4895..89adbf87cf 100644 --- a/packages/medusa/src/repositories/cart.ts +++ b/packages/medusa/src/repositories/cart.ts @@ -1,5 +1,53 @@ -import { EntityRepository, Repository } from "typeorm" +import { EntityRepository, FindManyOptions, Repository } from "typeorm" +import { flatten, groupBy, map, merge } from "lodash" import { Cart } from "../models/cart" @EntityRepository(Cart) -export class CartRepository extends Repository {} +export class CartRepository extends Repository { + public async findWithRelations( + relations: Array = [], + optionsWithoutRelations: Omit, "relations"> = {} + ): Promise { + const entities = await this.find(optionsWithoutRelations) + const entitiesIds = entities.map(({ id }) => id) + + const groupedRelations = {} + for (const rel of relations) { + const [topLevel] = rel.split(".") + if (groupedRelations[topLevel]) { + groupedRelations[topLevel].push(rel) + } else { + groupedRelations[topLevel] = [rel] + } + } + + const entitiesIdsWithRelations = await Promise.all( + Object.entries(groupedRelations).map(([_, rels]) => { + return this.findByIds(entitiesIds, { + select: ["id"], + relations: rels as string[], + }) + }) + ).then(flatten) + const entitiesAndRelations = entitiesIdsWithRelations.concat(entities) + + const entitiesAndRelationsById = groupBy(entitiesAndRelations, "id") + return map(entitiesAndRelationsById, entityAndRelations => + merge({}, ...entityAndRelations) + ) + } + + public async findOneWithRelations( + relations: Array = [], + optionsWithoutRelations: Omit, "relations"> = {} + ): Promise { + // Limit 1 + optionsWithoutRelations.take = 1 + + const result = await this.findWithRelations( + relations, + optionsWithoutRelations + ) + return result[0] + } +} diff --git a/packages/medusa/src/services/__tests__/cart.js b/packages/medusa/src/services/__tests__/cart.js index b268ff4740..ded354f5ee 100644 --- a/packages/medusa/src/services/__tests__/cart.js +++ b/packages/medusa/src/services/__tests__/cart.js @@ -34,7 +34,8 @@ describe("CartService", () => { describe("retrieve", () => { let result const cartRepository = MockRepository({ - findOne: () => Promise.resolve({ id: IdMap.getId("emptyCart") }), + findOneWithRelations: () => + Promise.resolve({ id: IdMap.getId("emptyCart") }), }) beforeAll(async () => { jest.clearAllMocks() @@ -47,10 +48,13 @@ describe("CartService", () => { }) it("calls cart model functions", () => { - expect(cartRepository.findOne).toHaveBeenCalledTimes(1) - expect(cartRepository.findOne).toHaveBeenCalledWith({ - where: { id: IdMap.getId("emptyCart") }, - }) + expect(cartRepository.findOneWithRelations).toHaveBeenCalledTimes(1) + expect(cartRepository.findOneWithRelations).toHaveBeenCalledWith( + undefined, + { + where: { id: IdMap.getId("emptyCart") }, + } + ) }) }) @@ -314,7 +318,7 @@ describe("CartService", () => { } const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === IdMap.getId("cartWithLine")) { return Promise.resolve({ items: [ @@ -472,7 +476,7 @@ describe("CartService", () => { }, } const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === IdMap.getId("withShipping")) { return Promise.resolve({ shipping_methods: [ @@ -574,7 +578,7 @@ describe("CartService", () => { describe("update", () => { const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === "withpays") { return Promise.resolve({ payment_sessions: [ @@ -602,8 +606,8 @@ describe("CartService", () => { cartService.setPaymentSessions = jest.fn() await cartService.update("withpays", {}) - expect(cartRepository.findOne).toHaveBeenCalledWith({ - relations: [ + expect(cartRepository.findOneWithRelations).toHaveBeenCalledWith( + [ "items", "shipping_methods", "shipping_address", @@ -617,8 +621,10 @@ describe("CartService", () => { "discounts.rule", "discounts.regions", ], - where: { id: "withpays" }, - }) + { + where: { id: "withpays" }, + } + ) }) }) @@ -636,7 +642,7 @@ describe("CartService", () => { } const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === IdMap.getId("cannot")) { return Promise.resolve({ items: [ @@ -719,7 +725,7 @@ describe("CartService", () => { }, } const cartRepository = MockRepository({ - findOne: () => Promise.resolve({}), + findOneWithRelations: () => Promise.resolve({}), }) const cartService = new CartService({ manager: MockManager, @@ -792,7 +798,7 @@ describe("CartService", () => { describe("updateBillingAddress", () => { const cartRepository = MockRepository({ - findOne: () => + findOneWithRelations: () => Promise.resolve({ region: { countries: [{ iso_2: "us" }] }, }), @@ -854,7 +860,7 @@ describe("CartService", () => { describe("updateShippingAddress", () => { const cartRepository = MockRepository({ - findOne: () => + findOneWithRelations: () => Promise.resolve({ region: { countries: [{ iso_2: "us" }] }, }), @@ -957,7 +963,7 @@ describe("CartService", () => { ), } const cartRepository = MockRepository({ - findOne: () => + findOneWithRelations: () => Promise.resolve({ items: [ { @@ -1056,7 +1062,7 @@ describe("CartService", () => { describe("setPaymentSession", () => { const cartRepository = MockRepository({ - findOne: () => { + findOneWithRelations: () => { return Promise.resolve({ region: { payment_providers: [ @@ -1165,7 +1171,7 @@ describe("CartService", () => { } const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === IdMap.getId("cart-to-filter")) { return Promise.resolve(cart3) } @@ -1287,7 +1293,7 @@ describe("CartService", () => { }) const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { switch (q.where.id) { case IdMap.getId("lines"): return Promise.resolve(cart3) @@ -1420,7 +1426,7 @@ describe("CartService", () => { describe("applyDiscount", () => { const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === IdMap.getId("with-d")) { return Promise.resolve({ id: IdMap.getId("cart"), @@ -1599,7 +1605,7 @@ describe("CartService", () => { describe("removeDiscount", () => { const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { return Promise.resolve({ id: IdMap.getId("cart"), discounts: [ diff --git a/packages/medusa/src/services/cart.js b/packages/medusa/src/services/cart.js index cd9bf09ced..6d1a2f1b1a 100644 --- a/packages/medusa/src/services/cart.js +++ b/packages/medusa/src/services/cart.js @@ -269,7 +269,9 @@ class CartService extends BaseService { query.select = select } - const raw = await cartRepo.findOne(query) + const rels = query.relations + delete query.relations + const raw = await cartRepo.findOneWithRelations(rels, query) if (!raw) { throw new MedusaError(