diff --git a/.changeset/fast-toes-know.md b/.changeset/fast-toes-know.md new file mode 100644 index 0000000000..86ca166dd2 --- /dev/null +++ b/.changeset/fast-toes-know.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": patch +--- + +fix(medusa): List products end points diff --git a/packages/medusa/src/api/routes/admin/products/list-products.ts b/packages/medusa/src/api/routes/admin/products/list-products.ts index da3a53e675..a85695e365 100644 --- a/packages/medusa/src/api/routes/admin/products/list-products.ts +++ b/packages/medusa/src/api/routes/admin/products/list-products.ts @@ -231,32 +231,42 @@ export default async (req, res) => { const { skip, take, relations } = req.listConfig - const [rawProducts, count] = await productService.listAndCount( - req.filterableFields, - req.listConfig + const manager = req.scope.resolve("manager") + + const [products, count] = await manager.transaction( + async (transactionManager) => { + const [rawProducts, count] = await productService + .withTransaction(transactionManager) + .listAndCount(req.filterableFields, req.listConfig) + + let products: (Product | PricedProduct)[] = rawProducts + + const includesPricing = ["variants", "variants.prices"].every( + (relation) => relations?.includes(relation) + ) + if (includesPricing) { + products = await pricingService + .withTransaction(transactionManager) + .setProductPrices(rawProducts) + } + + if (inventoryService) { + const [salesChannelsIds] = await salesChannelService + .withTransaction(transactionManager) + .listAndCount({}, { select: ["id"] }) + + products = await productVariantInventoryService + .withTransaction(transactionManager) + .setProductAvailability( + products, + salesChannelsIds.map((salesChannel) => salesChannel.id) + ) + } + + return [products, count] + } ) - let products: (Product | PricedProduct)[] = rawProducts - - const includesPricing = ["variants", "variants.prices"].every((relation) => - relations?.includes(relation) - ) - if (includesPricing) { - products = await pricingService.setProductPrices(rawProducts) - } - - if (inventoryService) { - const [salesChannelsIds] = await salesChannelService.listAndCount( - {}, - { select: ["id"] } - ) - - products = await productVariantInventoryService.setProductAvailability( - products, - salesChannelsIds.map((salesChannel) => salesChannel.id) - ) - } - res.json({ products, count, diff --git a/packages/medusa/src/api/routes/store/products/list-products.ts b/packages/medusa/src/api/routes/store/products/list-products.ts index 2303d612a1..f13d81a836 100644 --- a/packages/medusa/src/api/routes/store/products/list-products.ts +++ b/packages/medusa/src/api/routes/store/products/list-products.ts @@ -20,7 +20,6 @@ import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators import { optionalBooleanMapper } from "../../../../utils/validators/is-boolean" import { IsType } from "../../../../utils/validators/is-type" import { cleanResponseData } from "../../../../utils/clean-response-data" -import { Cart, Product } from "../../../../models" import { defaultStoreCategoryScope } from "../product-categories" /** @@ -204,7 +203,7 @@ export default async (req, res) => { filterableFields["categories"] = { ...(filterableFields.categories || {}), // Store APIs are only allowed to query active and public categories - ...defaultStoreCategoryScope + ...defaultStoreCategoryScope, } if (req.publishableApiKeyScopes?.sales_channel_ids.length) { @@ -217,47 +216,62 @@ export default async (req, res) => { } } - const promises: Promise[] = [] + const manager = req.scope.resolve("manager") - promises.push(productService.listAndCount(filterableFields, listConfig)) + const [computedProducts, count] = await manager.transaction( + async (transactionManager) => { + const promises: Promise[] = [] - if (validated.cart_id) { - promises.push( - cartService.retrieve(validated.cart_id, { - select: ["id", "region_id"] as any, - relations: ["region"], - }) - ) - } + promises.push( + productService + .withTransaction(transactionManager) + .listAndCount(filterableFields, listConfig) + ) - const [[rawProducts, count], cart] = (await Promise.all(promises)) as [ - [Product[], number], - Cart - ] + if (validated.cart_id) { + promises.push( + cartService + .withTransaction(transactionManager) + .retrieve(validated.cart_id, { + select: ["id", "region_id"] as any, + relations: ["region"], + }) + ) + } - if (validated.cart_id) { - regionId = cart.region_id - currencyCode = cart.region.currency_code - } + const [[rawProducts, count], cart] = await Promise.all(promises) - // Create a new reference just for naming purpose - const computedProducts = rawProducts + if (validated.cart_id) { + regionId = cart.region_id + currencyCode = cart.region.currency_code + } - // We can run them concurrently as the new properties are assigned to the references - // of the appropriate entity - await Promise.all([ - pricingService.setProductPrices(computedProducts, { - cart_id: cart_id, - region_id: regionId, - currency_code: currencyCode, - customer_id: req.user?.customer_id, - include_discount_prices: true, - }), - productVariantInventoryService.setProductAvailability( - computedProducts, - filterableFields.sales_channel_id - ), - ]) + // Create a new reference just for naming purpose + const computedProducts = rawProducts + + // We can run them concurrently as the new properties are assigned to the references + // of the appropriate entity + await Promise.all([ + pricingService + .withTransaction(transactionManager) + .setProductPrices(computedProducts, { + cart_id: cart_id, + region_id: regionId, + currency_code: currencyCode, + customer_id: req.user?.customer_id, + include_discount_prices: true, + }), + productVariantInventoryService + .withTransaction(transactionManager) + .setProductAvailability( + computedProducts, + filterableFields.sales_channel_id + ), + ]) + + return [computedProducts, count] + } + ) res.json({ products: cleanResponseData(computedProducts, req.allowedProperties || []),