diff --git a/.changeset/moody-cycles-explain.md b/.changeset/moody-cycles-explain.md new file mode 100644 index 0000000000..7db9a6bb88 --- /dev/null +++ b/.changeset/moody-cycles-explain.md @@ -0,0 +1,6 @@ +--- +"@medusajs/medusa": patch +"@medusajs/modules-sdk": patch +--- + +Feat/update cart product isolation diff --git a/packages/medusa/src/api/routes/store/carts/update-cart.ts b/packages/medusa/src/api/routes/store/carts/update-cart.ts index 8952a3ab61..5d59b65cd2 100644 --- a/packages/medusa/src/api/routes/store/carts/update-cart.ts +++ b/packages/medusa/src/api/routes/store/carts/update-cart.ts @@ -15,6 +15,7 @@ import { AddressPayload } from "../../../../types/common" import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators" import { IsType } from "../../../../utils/validators/is-type" import { cleanResponseData } from "../../../../utils/clean-response-data" +import IsolateProductDomainFeatureFlag from "../../../../loaders/feature-flags/isolate-product-domain" /** * @oas [post] /store/carts/{id} @@ -75,14 +76,22 @@ export default async (req, res) => { const validated = req.validatedBody as StorePostCartsCartReq const cartService: CartService = req.scope.resolve("cartService") + const featureFlagRouter = req.scope.resolve("featureFlagRouter") const manager: EntityManager = req.scope.resolve("manager") if (req.user?.customer_id) { validated.customer_id = req.user.customer_id } + let cart + if (featureFlagRouter.isFeatureEnabled(IsolateProductDomainFeatureFlag.key)) { + cart = await retrieveCartWithIsolatedProductModule(req, id) + } + await manager.transaction(async (transactionManager) => { - await cartService.withTransaction(transactionManager).update(id, validated) + await cartService + .withTransaction(transactionManager) + .update(cart ?? id, validated) const updated = await cartService .withTransaction(transactionManager) @@ -101,9 +110,60 @@ export default async (req, res) => { select: defaultStoreCartFields, relations: defaultStoreCartRelations, }) + res.json({ cart: cleanResponseData(data, []) }) } +async function retrieveCartWithIsolatedProductModule(req, id: string) { + const cartService = req.scope.resolve("cartService") + const remoteQuery = req.scope.resolve("remoteQuery") + + const relations = [ + "items", + "shipping_methods", + "shipping_methods.shipping_option", + "shipping_address", + "billing_address", + "gift_cards", + "customer", + "region", + "payment_sessions", + "region.countries", + "discounts", + "discounts.rule", + ] + + const cart = await cartService.retrieve(id, { + relations, + }) + + const products = await remoteQuery({ + products: { + __args: { + id: cart.items.map((i) => i.product_id), + }, + fields: ["id"], + variants: { + fields: ["id"], + }, + }, + }) + + const variantsMap = new Map( + products.flatMap((p) => p.variants).map((v) => [v.id, v]) + ) + + cart.items.forEach((item) => { + if (!item.variant_id) { + return + } + + item.variant = variantsMap.get(item.variant_id) + }) + + return cart +} + class GiftCard { @IsString() code: string diff --git a/packages/medusa/src/services/cart.ts b/packages/medusa/src/services/cart.ts index 7f1a0f596a..fdbcc5642b 100644 --- a/packages/medusa/src/services/cart.ts +++ b/packages/medusa/src/services/cart.ts @@ -1,10 +1,10 @@ import { FlagRouter } from "@medusajs/utils" import { isEmpty, isEqual } from "lodash" -import { MedusaError, isDefined } from "medusa-core-utils" +import { isDefined, MedusaError } from "medusa-core-utils" import { DeepPartial, EntityManager, In, IsNull, Not } from "typeorm" import { - CustomShippingOptionService, CustomerService, + CustomShippingOptionService, DiscountService, EventBusService, GiftCardService, @@ -29,8 +29,8 @@ import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels" import { Address, Cart, - CustomShippingOption, Customer, + CustomShippingOption, Discount, DiscountRule, DiscountRuleType, @@ -49,9 +49,9 @@ import { CartCreateProps, CartUpdateProps, FilterableCartProps, + isCart, LineItemUpdate, LineItemValidateData, - isCart, } from "../types/cart" import { AddressPayload, @@ -1098,7 +1098,7 @@ class CartService extends TransactionBaseService { } } - async update(cartId: string, data: CartUpdateProps): Promise { + async update(cartOrId: string | Cart, data: CartUpdateProps): Promise { return await this.atomicPhase_( async (transactionManager: EntityManager) => { const cartRepo = transactionManager.withRepository(this.cartRepository_) @@ -1117,9 +1117,11 @@ class CartService extends TransactionBaseService { "discounts.rule", ] - const cart = await this.retrieve(cartId, { - relations, - }) + const cart = !isString(cartOrId) + ? cartOrId + : await this.retrieve(cartOrId, { + relations, + }) const originalCartCustomer = { ...(cart.customer ?? {}) } if (data.customer_id) { diff --git a/packages/modules-sdk/src/medusa-app.ts b/packages/modules-sdk/src/medusa-app.ts index 1678f1134c..6265c4d7f9 100644 --- a/packages/modules-sdk/src/medusa-app.ts +++ b/packages/modules-sdk/src/medusa-app.ts @@ -12,8 +12,8 @@ import { } from "@medusajs/types" import { ContainerRegistrationKeys, - ModulesSdkUtils, isObject, + ModulesSdkUtils, } from "@medusajs/utils" import { MODULE_PACKAGE_NAMES, Modules } from "./definitions" import { MedusaModule } from "./medusa-module" @@ -69,7 +69,7 @@ export async function MedusaApp({ modules: Record link: RemoteLink | undefined query: ( - query: string | RemoteJoinerQuery, + query: string | RemoteJoinerQuery | object, variables?: Record ) => Promise }> { @@ -152,7 +152,7 @@ export async function MedusaApp({ let link: RemoteLink | undefined = undefined let query: ( - query: string | RemoteJoinerQuery, + query: string | RemoteJoinerQuery | object, variables?: Record ) => Promise @@ -172,7 +172,7 @@ export async function MedusaApp({ customRemoteFetchData: remoteFetchData, }) query = async ( - query: string | RemoteJoinerQuery, + query: string | RemoteJoinerQuery | object, variables?: Record ) => { return await remoteQuery.query(query, variables)