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:
committed by
GitHub
parent
0490a1c67f
commit
0ffd790109
8
.changeset/dull-onions-punch.md
Normal file
8
.changeset/dull-onions-punch.md
Normal 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
|
||||
@@ -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 }[],
|
||||
|
||||
@@ -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[]>>
|
||||
|
||||
@@ -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 }[],
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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] })
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user