diff --git a/.changeset/dull-onions-punch.md b/.changeset/dull-onions-punch.md new file mode 100644 index 0000000000..9afedb8b10 --- /dev/null +++ b/.changeset/dull-onions-punch.md @@ -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 diff --git a/packages/core/core-flows/src/cart/steps/update-cart-items-translations.ts b/packages/core/core-flows/src/cart/steps/update-cart-items-translations.ts index 7137d54496..1a517dbbe5 100644 --- a/packages/core/core-flows/src/cart/steps/update-cart-items-translations.ts +++ b/packages/core/core-flows/src/cart/steps/update-cart-items-translations.ts @@ -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[], - 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 }[], diff --git a/packages/core/core-flows/src/common/steps/get-translated-line-items.ts b/packages/core/core-flows/src/common/steps/get-translated-line-items.ts index 14ae072eba..2ff107f0bb 100644 --- a/packages/core/core-flows/src/common/steps/get-translated-line-items.ts +++ b/packages/core/core-flows/src/common/steps/get-translated-line-items.ts @@ -43,6 +43,5 @@ const step = createStep( */ export const getTranslatedLineItemsStep = ( data: GetTranslatedLineItemsStepInput -): ReturnType> => step(data) as unknown as ReturnType< - StepFunction -> +): ReturnType> => + step(data) as unknown as ReturnType> diff --git a/packages/core/core-flows/src/order/steps/update-order-items-translations.ts b/packages/core/core-flows/src/order/steps/update-order-items-translations.ts index 6727269825..306cfd05c6 100644 --- a/packages/core/core-flows/src/order/steps/update-order-items-translations.ts +++ b/packages/core/core-flows/src/order/steps/update-order-items-translations.ts @@ -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[], - 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 }[], diff --git a/packages/core/core-flows/src/order/steps/update-order-shipping-methods-translations.ts b/packages/core/core-flows/src/order/steps/update-order-shipping-methods-translations.ts index dfae5759a5..923abf9f86 100644 --- a/packages/core/core-flows/src/order/steps/update-order-shipping-methods-translations.ts +++ b/packages/core/core-flows/src/order/steps/update-order-shipping-methods-translations.ts @@ -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( translatedShippingOptions.map((tos) => [tos.id, tos.name]) diff --git a/packages/core/modules-sdk/src/remote-query/__tests__/query-locale.spec.ts b/packages/core/modules-sdk/src/remote-query/__tests__/query-locale.spec.ts new file mode 100644 index 0000000000..09e1085527 --- /dev/null +++ b/packages/core/modules-sdk/src/remote-query/__tests__/query-locale.spec.ts @@ -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) + }) + }) +}) diff --git a/packages/core/modules-sdk/src/remote-query/query.ts b/packages/core/modules-sdk/src/remote-query/query.ts index b7dbddce1c..e04c52c94f 100644 --- a/packages/core/modules-sdk/src/remote-query/query.ts +++ b/packages/core/modules-sdk/src/remote-query/query.ts @@ -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, diff --git a/packages/core/types/src/joiner/index.ts b/packages/core/types/src/joiner/index.ts index c4f04b5183..921eacf397 100644 --- a/packages/core/types/src/joiner/index.ts +++ b/packages/core/types/src/joiner/index.ts @@ -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 diff --git a/packages/medusa/src/api/store/collections/[id]/route.ts b/packages/medusa/src/api/store/collections/[id]/route.ts index 5c5fdf08cd..62283d4cce 100644 --- a/packages/medusa/src/api/store/collections/[id]/route.ts +++ b/packages/medusa/src/api/store/collections/[id]/route.ts @@ -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, res: MedusaResponse ) => { - 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 }) } diff --git a/packages/medusa/src/api/store/collections/route.ts b/packages/medusa/src/api/store/collections/route.ts index 940a9d30d4..34d2a5c97e 100644 --- a/packages/medusa/src/api/store/collections/route.ts +++ b/packages/medusa/src/api/store/collections/route.ts @@ -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, res: MedusaResponse ) => { - 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, }) } diff --git a/packages/medusa/src/api/store/product-categories/[id]/route.ts b/packages/medusa/src/api/store/product-categories/[id]/route.ts index 05c4f38045..89e09a962a 100644 --- a/packages/medusa/src/api/store/product-categories/[id]/route.ts +++ b/packages/medusa/src/api/store/product-categories/[id]/route.ts @@ -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, res: MedusaResponse ) => { - 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] }) } diff --git a/packages/medusa/src/api/store/product-categories/route.ts b/packages/medusa/src/api/store/product-categories/route.ts index ff01518939..6674dd338a 100644 --- a/packages/medusa/src/api/store/product-categories/route.ts +++ b/packages/medusa/src/api/store/product-categories/route.ts @@ -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, @@ -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, diff --git a/packages/medusa/src/api/store/product-tags/[id]/route.ts b/packages/medusa/src/api/store/product-tags/[id]/route.ts index 2d0d608aad..2a6f77c070 100644 --- a/packages/medusa/src/api/store/product-tags/[id]/route.ts +++ b/packages/medusa/src/api/store/product-tags/[id]/route.ts @@ -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 }) } diff --git a/packages/medusa/src/api/store/product-tags/route.ts b/packages/medusa/src/api/store/product-tags/route.ts index d99f1d99dd..79af4e1c8d 100644 --- a/packages/medusa/src/api/store/product-tags/route.ts +++ b/packages/medusa/src/api/store/product-tags/route.ts @@ -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, @@ -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, diff --git a/packages/medusa/src/api/store/product-types/[id]/route.ts b/packages/medusa/src/api/store/product-types/[id]/route.ts index 51fa951793..24a499b602 100644 --- a/packages/medusa/src/api/store/product-types/[id]/route.ts +++ b/packages/medusa/src/api/store/product-types/[id]/route.ts @@ -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 }) } diff --git a/packages/medusa/src/api/store/product-types/route.ts b/packages/medusa/src/api/store/product-types/route.ts index 250799c116..aa454a5ec8 100644 --- a/packages/medusa/src/api/store/product-types/route.ts +++ b/packages/medusa/src/api/store/product-types/route.ts @@ -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, @@ -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, diff --git a/packages/medusa/src/api/store/product-variants/[id]/route.ts b/packages/medusa/src/api/store/product-variants/[id]/route.ts index d196c6fda2..223aa75057 100644 --- a/packages/medusa/src/api/store/product-variants/[id]/route.ts +++ b/packages/medusa/src/api/store/product-variants/[id]/route.ts @@ -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]) } diff --git a/packages/medusa/src/api/store/product-variants/route.ts b/packages/medusa/src/api/store/product-variants/route.ts index a5a5ef70d1..3e7d7e80e1 100644 --- a/packages/medusa/src/api/store/product-variants/route.ts +++ b/packages/medusa/src/api/store/product-variants/route.ts @@ -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 = - StoreRequestWithContext & - AuthenticatedMedusaRequest + StoreRequestWithContext & AuthenticatedMedusaRequest /** * @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) } diff --git a/packages/medusa/src/api/store/products/[id]/route.ts b/packages/medusa/src/api/store/products/[id]/route.ts index c1eba9fd46..5975ce75ea 100644 --- a/packages/medusa/src/api/store/products/[id]/route.ts +++ b/packages/medusa/src/api/store/products/[id]/route.ts @@ -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 }) } diff --git a/packages/medusa/src/api/store/products/route.ts b/packages/medusa/src/api/store/products/route.ts index 1f165b80d3..29513ba9b2 100644 --- a/packages/medusa/src/api/store/products/route.ts +++ b/packages/medusa/src/api/store/products/route.ts @@ -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,