feat(medusa): Add product isolation FF to update cart (#5168)

**What**
Update cart must use the remote query when being in product isolation mode.

This pr is a first iteration that aims to quickly make compatible the end point in isolation. In a future iteration, this end point will be migrated to a workflow

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Adrien de Peretti
2023-09-22 10:49:59 +02:00
committed by GitHub
parent 27d74cb399
commit dfa5d041c9
4 changed files with 81 additions and 13 deletions

View File

@@ -0,0 +1,6 @@
---
"@medusajs/medusa": patch
"@medusajs/modules-sdk": patch
---
Feat/update cart product isolation

View File

@@ -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

View File

@@ -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<Cart> {
async update(cartOrId: string | Cart, data: CartUpdateProps): Promise<Cart> {
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) {

View File

@@ -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<string, LoadedModule | LoadedModule[]>
link: RemoteLink | undefined
query: (
query: string | RemoteJoinerQuery,
query: string | RemoteJoinerQuery | object,
variables?: Record<string, unknown>
) => Promise<any>
}> {
@@ -152,7 +152,7 @@ export async function MedusaApp({
let link: RemoteLink | undefined = undefined
let query: (
query: string | RemoteJoinerQuery,
query: string | RemoteJoinerQuery | object,
variables?: Record<string, unknown>
) => Promise<any>
@@ -172,7 +172,7 @@ export async function MedusaApp({
customRemoteFetchData: remoteFetchData,
})
query = async (
query: string | RemoteJoinerQuery,
query: string | RemoteJoinerQuery | object,
variables?: Record<string, unknown>
) => {
return await remoteQuery.query(query, variables)