feat(translation): Add support for locale to the graph query (#14454)

* feat(translation): Add support for locale to the graph query

* feat(translation): Add support for locale to the graph query

* feat(translation): Add support for locale to the graph query

* feat(translation): fix import

* fix

* cleanup

* fix context in product routes

* Create dull-onions-punch.md
This commit is contained in:
Adrien de Peretti
2026-01-06 12:29:27 +01:00
committed by GitHub
parent 0490a1c67f
commit 0ffd790109
20 changed files with 531 additions and 236 deletions

View File

@@ -0,0 +1,8 @@
---
"@medusajs/medusa": patch
"@medusajs/core-flows": patch
"@medusajs/modules-sdk": patch
"@medusajs/types": patch
---
feat(translation): Add support for locale to the graph query

View File

@@ -5,7 +5,6 @@ import {
RemoteQueryFunction,
} from "@medusajs/framework/types"
import {
applyTranslations,
ContainerRegistrationKeys,
deduplicate,
FeatureFlag,
@@ -122,17 +121,16 @@ export const updateCartItemsTranslationsStep = createStep(
})
}
const { data: variants } = await query.graph({
entity: "variants",
filters: { id: variantIds },
fields: productVariantsFields,
})
await applyTranslations({
localeCode: data.locale,
objects: variants as Record<string, any>[],
container,
})
const { data: variants } = await query.graph(
{
entity: "variants",
filters: { id: variantIds },
fields: productVariantsFields,
},
{
locale: data.locale,
}
)
const translatedItems = applyTranslationsToItems(
items as { variant_id?: string; [key: string]: any }[],

View File

@@ -43,6 +43,5 @@ const step = createStep(
*/
export const getTranslatedLineItemsStep = <T>(
data: GetTranslatedLineItemsStepInput<T>
): ReturnType<StepFunction<any, T[]>> => step(data) as unknown as ReturnType<
StepFunction<any, T[]>
>
): ReturnType<StepFunction<any, T[]>> =>
step(data) as unknown as ReturnType<StepFunction<any, T[]>>

View File

@@ -5,7 +5,6 @@ import {
RemoteQueryFunction,
} from "@medusajs/framework/types"
import {
applyTranslations,
ContainerRegistrationKeys,
deduplicate,
FeatureFlag,
@@ -137,17 +136,16 @@ export const updateOrderItemsTranslationsStep = createStep(
})
}
const { data: variants } = await query.graph({
entity: "variants",
filters: { id: variantIds },
fields: productVariantsFields,
})
await applyTranslations({
localeCode: data.locale,
objects: variants as Record<string, any>[],
container,
})
const { data: variants } = await query.graph(
{
entity: "variants",
filters: { id: variantIds },
fields: productVariantsFields,
},
{
locale: data.locale,
}
)
const translatedItems = applyTranslationsToItems(
items as { variant_id?: string; [key: string]: any }[],

View File

@@ -1,5 +1,4 @@
import {
applyTranslations,
ContainerRegistrationKeys,
FeatureFlag,
Modules,
@@ -30,19 +29,18 @@ export const updateOrderShippingMethodsTranslationsStep = createStep(
const query = container.resolve(ContainerRegistrationKeys.QUERY)
const orderModuleService = container.resolve(Modules.ORDER)
const { data: translatedShippingOptions } = await query.graph({
entity: "shipping_option",
fields: ["id", "name"],
filters: {
id: data.shippingMethods.map((sm) => sm.shipping_option_id),
const { data: translatedShippingOptions } = await query.graph(
{
entity: "shipping_option",
fields: ["id", "name"],
filters: {
id: data.shippingMethods.map((sm) => sm.shipping_option_id),
},
},
})
await applyTranslations({
localeCode: data.locale,
objects: translatedShippingOptions,
container,
})
{
locale: data.locale,
}
)
const shippingOptionTranslationMap = new Map<string, string>(
translatedShippingOptions.map((tos) => [tos.id, tos.name])

View File

@@ -0,0 +1,301 @@
import { MedusaContainer } from "@medusajs/types"
import * as utils from "@medusajs/utils"
import { Query } from "../query"
jest.mock("@medusajs/utils", () => ({
...jest.requireActual("@medusajs/utils"),
applyTranslations: jest.fn(),
}))
const mockApplyTranslations = utils.applyTranslations as jest.Mock
function createMockRemoteQuery(queryResult: any = []) {
return {
query: jest.fn().mockResolvedValue(queryResult),
getEntitiesMap: jest.fn().mockReturnValue(new Map()),
}
}
function createMockContainer(): MedusaContainer {
return {
resolve: jest.fn(),
} as unknown as MedusaContainer
}
describe("Query.graph locale integration", () => {
beforeEach(() => {
jest.clearAllMocks()
})
describe("when locale option is provided", () => {
it("should call applyTranslations with the correct locale code", async () => {
const mockRemoteQuery = createMockRemoteQuery([
{ id: "prod_1", title: "Test" },
])
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
await query.graph(
{ entity: "product", fields: ["id", "title"] },
{ locale: "fr-FR" }
)
expect(mockApplyTranslations).toHaveBeenCalledTimes(1)
expect(mockApplyTranslations).toHaveBeenCalledWith({
localeCode: "fr-FR",
objects: expect.any(Array),
container: mockContainer,
})
})
it("should call applyTranslations with the result data array", async () => {
const resultData = [
{ id: "prod_1", title: "Product 1" },
{ id: "prod_2", title: "Product 2" },
]
const mockRemoteQuery = createMockRemoteQuery(resultData)
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
await query.graph(
{ entity: "product", fields: ["id", "title"] },
{ locale: "en-US" }
)
expect(mockApplyTranslations).toHaveBeenCalledWith(
expect.objectContaining({
objects: resultData,
})
)
})
it("should call applyTranslations with the container instance", async () => {
const mockRemoteQuery = createMockRemoteQuery([])
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
await query.graph(
{ entity: "product", fields: ["id"] },
{ locale: "de-DE" }
)
expect(mockApplyTranslations).toHaveBeenCalledWith(
expect.objectContaining({
container: mockContainer,
})
)
})
it("should call applyTranslations for paginated results", async () => {
const paginatedResult = {
rows: [{ id: "prod_1" }, { id: "prod_2" }],
metadata: { skip: 0, take: 10, count: 2 },
}
const mockRemoteQuery = createMockRemoteQuery(paginatedResult)
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
await query.graph(
{
entity: "product",
fields: ["id"],
pagination: { skip: 0, take: 10 },
},
{ locale: "es-ES" }
)
expect(mockApplyTranslations).toHaveBeenCalledWith(
expect.objectContaining({
objects: paginatedResult.rows,
})
)
})
})
describe("when locale option is NOT provided", () => {
it("should NOT call applyTranslations when options is undefined", async () => {
const mockRemoteQuery = createMockRemoteQuery([{ id: "prod_1" }])
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
await query.graph({ entity: "product", fields: ["id"] })
expect(mockApplyTranslations).not.toHaveBeenCalled()
})
it("should NOT call applyTranslations when options is an empty object", async () => {
const mockRemoteQuery = createMockRemoteQuery([{ id: "prod_1" }])
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
await query.graph({ entity: "product", fields: ["id"] }, {})
expect(mockApplyTranslations).not.toHaveBeenCalled()
})
it("should NOT call applyTranslations when locale is explicitly undefined", async () => {
const mockRemoteQuery = createMockRemoteQuery([{ id: "prod_1" }])
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
await query.graph(
{ entity: "product", fields: ["id"] },
{ locale: undefined }
)
expect(mockApplyTranslations).not.toHaveBeenCalled()
})
it("should NOT call applyTranslations when other options are provided but locale is missing", async () => {
const mockRemoteQuery = createMockRemoteQuery([{ id: "prod_1" }])
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
await query.graph(
{ entity: "product", fields: ["id"] },
{ throwIfKeyNotFound: true }
)
expect(mockApplyTranslations).not.toHaveBeenCalled()
})
})
describe("applyTranslations parameter validation", () => {
it("should pass empty array to applyTranslations when query returns empty array", async () => {
const mockRemoteQuery = createMockRemoteQuery([])
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
await query.graph(
{ entity: "product", fields: ["id"] },
{ locale: "fr-FR" }
)
expect(mockApplyTranslations).toHaveBeenCalledWith({
localeCode: "fr-FR",
objects: [],
container: mockContainer,
})
})
it("should preserve all three parameters correctly", async () => {
const resultData = [{ id: "test_1" }]
const mockRemoteQuery = createMockRemoteQuery(resultData)
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
await query.graph(
{ entity: "product", fields: ["id"] },
{ locale: "pt-BR" }
)
const callArgs = mockApplyTranslations.mock.calls[0][0]
expect(callArgs).toHaveProperty("localeCode", "pt-BR")
expect(callArgs).toHaveProperty("objects", resultData)
expect(callArgs).toHaveProperty("container", mockContainer)
})
it("should work with different locale formats", async () => {
const mockRemoteQuery = createMockRemoteQuery([{ id: "prod_1" }])
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
const locales = ["en", "en-US", "zh-Hans-CN", "pt-BR"]
for (const locale of locales) {
jest.clearAllMocks()
await query.graph({ entity: "product", fields: ["id"] }, { locale })
expect(mockApplyTranslations).toHaveBeenCalledWith(
expect.objectContaining({ localeCode: locale })
)
}
})
})
describe("return value behavior with locale", () => {
it("should return the result after applyTranslations is called", async () => {
const resultData = [{ id: "prod_1", title: "Original" }]
const mockRemoteQuery = createMockRemoteQuery(resultData)
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
const result = await query.graph(
{ entity: "product", fields: ["id", "title"] },
{ locale: "fr-FR" }
)
expect(result).toEqual({
data: resultData,
metadata: undefined,
})
})
it("should return the same reference that was passed to applyTranslations", async () => {
const resultData = [{ id: "prod_1" }]
const mockRemoteQuery = createMockRemoteQuery(resultData)
const mockContainer = createMockContainer()
const query = new Query({
remoteQuery: mockRemoteQuery as any,
indexModule: null as any,
container: mockContainer,
})
const result = await query.graph(
{ entity: "product", fields: ["id"] },
{ locale: "de-DE" }
)
const passedObjects = mockApplyTranslations.mock.calls[0][0].objects
expect(result.data).toBe(passedObjects)
})
})
})

View File

@@ -14,6 +14,7 @@ import {
import {
Cached,
MedusaError,
applyTranslations,
isObject,
remoteQueryObjectFromString,
unflattenObjectKeys,
@@ -238,7 +239,17 @@ export class Query {
)
}
return this.#unwrapRemoteQueryResponse(response)
const result = this.#unwrapRemoteQueryResponse(response)
if (options?.locale) {
await applyTranslations({
localeCode: options.locale,
objects: result.data,
container: this.container,
})
}
return result
}
/**
@@ -309,6 +320,14 @@ export class Query {
})
}
if (options?.locale) {
await applyTranslations({
localeCode: options.locale,
objects: finalResultset.data,
container: this.container,
})
}
return {
data: finalResultset.data,
metadata: indexResponse.metadata as RemoteQueryFunctionReturnPagination,

View File

@@ -94,6 +94,11 @@ export interface RemoteJoinerOptions {
throwIfRelationNotFound?: boolean | string[]
initialData?: object | object[]
initialDataOnly?: boolean
/**
* The locale to use for the query.
* Translation will be applied to the query result based on the locale.
*/
locale?: string
cache?: {
/**
* Whether to enable the cache. This is only useful if you want to enable without providing any

View File

@@ -1,26 +1,37 @@
import { HttpTypes } from "@medusajs/framework/types"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { refetchCollection } from "../helpers"
import { applyTranslations } from "@medusajs/framework/utils"
import { HttpTypes } from "@medusajs/framework/types"
import {
ContainerRegistrationKeys,
MedusaError,
} from "@medusajs/framework/utils"
export const GET = async (
req: AuthenticatedMedusaRequest<HttpTypes.SelectParams>,
res: MedusaResponse<HttpTypes.StoreCollectionResponse>
) => {
const collection = await refetchCollection(
req.params.id,
req.scope,
req.queryConfig.fields
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const { data: collections } = await query.graph(
{
entity: "product_collection",
filters: { id: req.params.id },
fields: req.queryConfig.fields,
},
{
locale: req.locale,
}
)
await applyTranslations({
localeCode: req.locale,
objects: [collection],
container: req.scope,
})
const collection = collections[0]
if (!collection) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Collection with id: ${req.params.id} was not found`
)
}
res.status(200).json({ collection })
res.status(200).json({ collection: collection })
}

View File

@@ -1,42 +1,33 @@
import { HttpTypes } from "@medusajs/framework/types"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { HttpTypes } from "@medusajs/framework/types"
import {
applyTranslations,
ContainerRegistrationKeys,
remoteQueryObjectFromString,
} from "@medusajs/framework/utils"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
export const GET = async (
req: AuthenticatedMedusaRequest<HttpTypes.StoreCollectionListParams>,
res: MedusaResponse<HttpTypes.StoreCollectionListResponse>
) => {
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const query = remoteQueryObjectFromString({
entryPoint: "product_collection",
variables: {
const { data: collections, metadata } = await query.graph(
{
entity: "product_collection",
filters: req.filterableFields,
...req.queryConfig.pagination,
pagination: req.queryConfig.pagination,
fields: req.queryConfig.fields,
},
fields: req.queryConfig.fields,
})
const { rows: collections, metadata } = await remoteQuery(query)
await applyTranslations({
localeCode: req.locale,
objects: collections,
container: req.scope,
})
{
locale: req.locale,
}
)
res.json({
collections,
count: metadata.count,
offset: metadata.skip,
limit: metadata.take,
count: metadata!.count,
offset: metadata!.skip,
limit: metadata!.take,
})
}

View File

@@ -1,22 +1,30 @@
import { StoreProductCategoryResponse } from "@medusajs/framework/types"
import { applyTranslations, MedusaError } from "@medusajs/framework/utils"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
refetchEntity,
} from "@medusajs/framework/http"
import { StoreProductCategoryResponse } from "@medusajs/framework/types"
import {
ContainerRegistrationKeys,
MedusaError,
} from "@medusajs/framework/utils"
import { StoreProductCategoryParamsType } from "../validators"
export const GET = async (
req: AuthenticatedMedusaRequest<StoreProductCategoryParamsType>,
res: MedusaResponse<StoreProductCategoryResponse>
) => {
const category = await refetchEntity({
entity: "product_category",
idOrFilter: { id: req.params.id, ...req.filterableFields },
scope: req.scope,
fields: req.queryConfig.fields,
})
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const { data: category } = await query.graph(
{
entity: "product_category",
filters: { id: req.params.id, ...req.filterableFields },
fields: req.queryConfig.fields,
},
{
locale: req.locale,
}
)
if (!category) {
throw new MedusaError(
@@ -25,11 +33,5 @@ export const GET = async (
)
}
await applyTranslations({
localeCode: req.locale,
objects: [category],
container: req.scope,
})
res.json({ product_category: category })
res.json({ product_category: category[0] })
}

View File

@@ -6,10 +6,7 @@ import {
StoreProductCategoryListParams,
StoreProductCategoryListResponse,
} from "@medusajs/framework/types"
import {
applyTranslations,
ContainerRegistrationKeys,
} from "@medusajs/framework/utils"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
export const GET = async (
req: AuthenticatedMedusaRequest<StoreProductCategoryListParams>,
@@ -17,18 +14,17 @@ export const GET = async (
) => {
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const { data: product_categories, metadata } = await query.graph({
entity: "product_category",
fields: req.queryConfig.fields,
filters: req.filterableFields,
pagination: req.queryConfig.pagination,
})
await applyTranslations({
localeCode: req.locale,
objects: product_categories,
container: req.scope,
})
const { data: product_categories, metadata } = await query.graph(
{
entity: "product_category",
fields: req.queryConfig.fields,
filters: req.filterableFields,
pagination: req.queryConfig.pagination,
},
{
locale: req.locale,
}
)
res.json({
product_categories,

View File

@@ -1,13 +1,12 @@
import { StoreProductTagResponse } from "@medusajs/framework/types"
import {
applyTranslations,
ContainerRegistrationKeys,
MedusaError,
} from "@medusajs/framework/utils"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { StoreProductTagResponse } from "@medusajs/framework/types"
import {
ContainerRegistrationKeys,
MedusaError,
} from "@medusajs/framework/utils"
import { StoreProductTagParamsType } from "../validators"
@@ -17,13 +16,18 @@ export const GET = async (
) => {
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const { data } = await query.graph({
entity: "product_tag",
filters: {
id: req.params.id,
const { data } = await query.graph(
{
entity: "product_tag",
filters: {
id: req.params.id,
},
fields: req.queryConfig.fields,
},
fields: req.queryConfig.fields,
})
{
locale: req.locale,
}
)
if (!data.length) {
throw new MedusaError(
@@ -34,11 +38,5 @@ export const GET = async (
const productTag = data[0]
await applyTranslations({
localeCode: req.locale,
objects: [productTag],
container: req.scope,
})
res.json({ product_tag: productTag })
}

View File

@@ -1,12 +1,9 @@
import { HttpTypes } from "@medusajs/framework/types"
import {
applyTranslations,
ContainerRegistrationKeys,
} from "@medusajs/framework/utils"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { HttpTypes } from "@medusajs/framework/types"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
export const GET = async (
req: AuthenticatedMedusaRequest<HttpTypes.StoreProductTagListParams>,
@@ -14,18 +11,17 @@ export const GET = async (
) => {
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const { data: product_tags, metadata } = await query.graph({
entity: "product_tag",
filters: req.filterableFields,
pagination: req.queryConfig.pagination,
fields: req.queryConfig.fields,
})
await applyTranslations({
localeCode: req.locale,
objects: product_tags,
container: req.scope,
})
const { data: product_tags, metadata } = await query.graph(
{
entity: "product_tag",
filters: req.filterableFields,
pagination: req.queryConfig.pagination,
fields: req.queryConfig.fields,
},
{
locale: req.locale,
}
)
res.json({
product_tags,

View File

@@ -1,13 +1,12 @@
import { StoreProductTypeResponse } from "@medusajs/framework/types"
import {
applyTranslations,
ContainerRegistrationKeys,
MedusaError,
} from "@medusajs/framework/utils"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { StoreProductTypeResponse } from "@medusajs/framework/types"
import {
ContainerRegistrationKeys,
MedusaError,
} from "@medusajs/framework/utils"
import { StoreProductTypeParamsType } from "../validators"
@@ -17,13 +16,18 @@ export const GET = async (
) => {
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const { data } = await query.graph({
entity: "product_type",
filters: {
id: req.params.id,
const { data } = await query.graph(
{
entity: "product_type",
filters: {
id: req.params.id,
},
fields: req.queryConfig.fields,
},
fields: req.queryConfig.fields,
})
{
locale: req.locale,
}
)
if (!data.length) {
throw new MedusaError(
@@ -34,11 +38,5 @@ export const GET = async (
const productType = data[0]
await applyTranslations({
localeCode: req.locale,
objects: [productType],
container: req.scope,
})
res.json({ product_type: productType })
}

View File

@@ -1,12 +1,9 @@
import { HttpTypes } from "@medusajs/framework/types"
import {
applyTranslations,
ContainerRegistrationKeys,
} from "@medusajs/framework/utils"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { HttpTypes } from "@medusajs/framework/types"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
export const GET = async (
req: AuthenticatedMedusaRequest<HttpTypes.StoreProductTypeListParams>,
@@ -14,18 +11,17 @@ export const GET = async (
) => {
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const { data: product_types, metadata } = await query.graph({
entity: "product_type",
filters: req.filterableFields,
pagination: req.queryConfig.pagination,
fields: req.queryConfig.fields,
})
await applyTranslations({
localeCode: req.locale,
objects: product_types,
container: req.scope,
})
const { data: product_types, metadata } = await query.graph(
{
entity: "product_type",
filters: req.filterableFields,
pagination: req.queryConfig.pagination,
fields: req.queryConfig.fields,
},
{
locale: req.locale,
}
)
res.json({
product_types,

View File

@@ -4,7 +4,6 @@ import {
} from "@medusajs/framework/http"
import { HttpTypes, QueryContextType } from "@medusajs/framework/types"
import {
applyTranslations,
ContainerRegistrationKeys,
MedusaError,
QueryContext,
@@ -42,15 +41,20 @@ export const GET = async (
context["calculated_price"] = QueryContext(req.pricingContext)
}
const { data: variants = [] } = await query.graph({
entity: "variant",
filters: {
...req.filterableFields,
id: req.params.id,
const { data: variants = [] } = await query.graph(
{
entity: "variant",
filters: {
...req.filterableFields,
id: req.params.id,
},
fields: req.queryConfig.fields,
context,
},
fields: req.queryConfig.fields,
context,
})
{
locale: req.locale,
}
)
const variant = variants[0]
@@ -61,12 +65,6 @@ export const GET = async (
)
}
await applyTranslations({
localeCode: req.locale,
objects: [variant],
container: req.scope,
})
if (withInventoryQuantity) {
await wrapVariantsWithInventoryQuantityForSalesChannel(req, [variant])
}

View File

@@ -4,7 +4,6 @@ import {
} from "@medusajs/framework/http"
import { HttpTypes, QueryContextType } from "@medusajs/framework/types"
import {
applyTranslations,
ContainerRegistrationKeys,
QueryContext,
} from "@medusajs/framework/utils"
@@ -13,8 +12,7 @@ import { StoreRequestWithContext } from "../types"
import { wrapVariantsWithTaxPrices } from "./helpers"
type StoreVariantListRequest<T = HttpTypes.StoreProductVariantParams> =
StoreRequestWithContext<T> &
AuthenticatedMedusaRequest<T>
StoreRequestWithContext<T> & AuthenticatedMedusaRequest<T>
/**
* @since 2.11.2
@@ -52,15 +50,10 @@ export const GET = async (
cache: {
enable: true,
},
locale: req.locale,
}
)
await applyTranslations({
localeCode: req.locale,
objects: variants,
container: req.scope,
})
if (withInventoryQuantity) {
await wrapVariantsWithInventoryQuantityForSalesChannel(req, variants)
}

View File

@@ -1,15 +1,13 @@
import { MedusaResponse } from "@medusajs/framework/http"
import { HttpTypes } from "@medusajs/framework/types"
import { HttpTypes, QueryContextType } from "@medusajs/framework/types"
import {
applyTranslations,
isPresent,
ContainerRegistrationKeys,
MedusaError,
QueryContext,
} from "@medusajs/framework/utils"
import { wrapVariantsWithInventoryQuantityForSalesChannel } from "../../../utils/middlewares"
import {
filterOutInternalProductCategories,
refetchProduct,
RequestWithContext,
wrapProductsWithTaxPrices,
} from "../helpers"
@@ -33,12 +31,11 @@ export const GET = async (
...req.filterableFields,
}
if (isPresent(req.pricingContext)) {
filters["context"] ??= {}
filters["context"]["variants"] ??= {}
filters["context"]["variants"]["calculated_price"] ??= QueryContext(
req.pricingContext!
)
const context: QueryContextType = {}
if (req.pricingContext) {
context["variants"] ??= {}
context["variants"]["calculated_price"] ??= QueryContext(req.pricingContext)
}
const includesCategoriesField = req.queryConfig.fields.some((field) =>
@@ -49,11 +46,20 @@ export const GET = async (
req.queryConfig.fields.push("categories.is_internal")
}
const product = await refetchProduct(
filters,
req.scope,
req.queryConfig.fields
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const { data: products } = await query.graph(
{
entity: "product",
filters,
context,
fields: req.queryConfig.fields,
},
{
locale: req.locale,
}
)
const product = products[0]
if (!product) {
throw new MedusaError(
@@ -74,10 +80,5 @@ export const GET = async (
}
await wrapProductsWithTaxPrices(req, [product])
await applyTranslations({
localeCode: req.locale,
objects: [product],
container: req.scope,
})
res.json({ product })
}

View File

@@ -1,7 +1,6 @@
import { MedusaResponse } from "@medusajs/framework/http"
import { HttpTypes, QueryContextType } from "@medusajs/framework/types"
import {
applyTranslations,
ContainerRegistrationKeys,
FeatureFlag,
isPresent,
@@ -76,6 +75,7 @@ async function getProductsWithIndexEngine(
cache: {
enable: true,
},
locale: req.locale,
}
)
@@ -88,12 +88,6 @@ async function getProductsWithIndexEngine(
await wrapProductsWithTaxPrices(req, products)
await applyTranslations({
localeCode: req.locale,
objects: products,
container: req.scope,
})
res.json({
products,
count: metadata!.estimate_count,
@@ -138,6 +132,7 @@ async function getProducts(
cache: {
enable: true,
},
locale: req.locale,
}
)
@@ -150,12 +145,6 @@ async function getProducts(
await wrapProductsWithTaxPrices(req, products)
await applyTranslations({
localeCode: req.locale,
objects: products,
container: req.scope,
})
res.json({
products,
count: metadata!.count,