chore: Processing filters deeply looking at the current joiner first (#9428)

* chore: Processing filters deeply looking at the current joiner first

* fix

* fix
This commit is contained in:
Adrien de Peretti
2024-10-02 14:17:12 +02:00
committed by GitHub
parent 8155c4e9ee
commit 8753b178da
3 changed files with 124 additions and 14 deletions

View File

@@ -2,6 +2,27 @@ import { defineJoinerConfig } from "@medusajs/utils"
import { MedusaModule } from "../../medusa-module"
import { ModuleJoinerConfig } from "@medusajs/types"
const customModuleJoinerConfig = defineJoinerConfig("custom_user", {
schema: `
type CustomProduct {
id: ID
title: String
product: Product
}
type Product {
id: ID
title: String
}
`,
alias: [
{
name: ["custom_products", "custom_product"],
entity: "CustomProduct",
},
],
})
const productJoinerConfig = defineJoinerConfig("product", {
schema: `
type Product {
@@ -154,6 +175,7 @@ const linkProductVariantPriceSet = {
MedusaModule.setJoinerConfig("product", productJoinerConfig)
MedusaModule.setJoinerConfig("pricing", pricingJoinerConfig)
MedusaModule.setJoinerConfig("customProduct", customModuleJoinerConfig)
MedusaModule.setJoinerConfig(
"link-product-variant-price-set",
linkProductVariantPriceSet

View File

@@ -11,6 +11,44 @@ const entitiesMap = getEntitiesMap(
describe("parse-filters", () => {
describe("Without operator map usage", () => {
it(`should parse filter for a single level module with ambiguous entity`, () => {
const filters = {
id: "string",
product: {
title: "test",
},
}
const remoteQueryObject = {
custom_product: {
fields: ["id", "product.*"],
},
}
parseAndAssignFilters(
{
remoteQueryObject,
entryPoint: "custom_product",
filters,
},
entitiesMap
)
expect(remoteQueryObject).toEqual({
custom_product: {
fields: ["id", "product.*"],
__args: {
filters: {
id: "string",
product: {
title: "test",
},
},
},
},
})
})
it("should parse filter for a single level module", () => {
const filters = {
id: "string",

View File

@@ -1,8 +1,4 @@
import {
JoinerServiceConfig,
JoinerServiceConfigAlias,
ModuleJoinerConfig,
} from "@medusajs/types"
import { JoinerServiceConfig, ModuleJoinerConfig } from "@medusajs/types"
import { isObject, isString } from "@medusajs/utils"
import { MedusaModule } from "../medusa-module"
@@ -33,23 +29,25 @@ export function parseAndAssignFilters(
const joinerConfigs = MedusaModule.getAllJoinerConfigs()
for (const [filterKey, filterValue] of Object.entries(filters)) {
let entryAlias!: JoinerServiceConfigAlias
/*let entryAlias!: JoinerServiceConfigAlias*/
let entryJoinerConfig!: JoinerServiceConfig
const { joinerConfig, alias } = retrieveJoinerConfigFromPropertyName({
const { joinerConfig /*alias*/ } = retrieveJoinerConfigFromPropertyName({
entryPoint: entryPoint,
joinerConfigs,
})
entryAlias = alias
/*JoinerServiceConfigentryAlias = alias!*/
entryJoinerConfig = joinerConfig
const entryEntity = entitiesMap[entryAlias.entity!]
// TODO: This check is not used further than to validate the entity is part of the graphql schema
// This can't be used right now as we have not migrated the entire code base to DML from which the graphql schema is generated
/*const entryEntity = entitiesMap[entryAlias.entity!]
if (!entryEntity) {
throw new Error(
`Entity ${entryAlias.entity} not found in the public schema of the joiner config from ${entryJoinerConfig.serviceName}`
)
}
}*/
if (isObject(filterValue)) {
for (const [nestedFilterKey, nestedFilterValue] of Object.entries(
@@ -58,6 +56,7 @@ export function parseAndAssignFilters(
const { joinerConfig: filterKeyJoinerConfig } =
retrieveJoinerConfigFromPropertyName({
entryPoint: nestedFilterKey,
parentJoinerConfig: joinerConfig,
joinerConfigs,
})
@@ -85,7 +84,7 @@ export function parseAndAssignFilters(
parseAndAssignFilters(
{
entryPoint: nestedFilterKey,
filters: nestedFilterValue,
filters: nestedFilterValue as object,
remoteQueryObject: remoteQueryObject[entryPoint][filterKey],
isFieldAliasNestedRelation: isFieldAliasNestedRelation_,
},
@@ -107,16 +106,38 @@ export function parseAndAssignFilters(
}
}
function retrieveJoinerConfigFromPropertyName({ entryPoint, joinerConfigs }) {
function retrieveJoinerConfigFromPropertyName({
entryPoint,
parentJoinerConfig,
joinerConfigs,
}: {
entryPoint: string
parentJoinerConfig?: ModuleJoinerConfig
joinerConfigs: ModuleJoinerConfig[]
}) {
if (parentJoinerConfig) {
const res = findAliasFromJoinerConfig({
joinerConfig: parentJoinerConfig,
entryPoint,
})
if (res) {
return res
}
}
if (joinerConfigMapCache.has(entryPoint)) {
return joinerConfigMapCache.get(entryPoint)!
}
for (const joinerConfig of joinerConfigs) {
const aliases = joinerConfig.alias
const joinerConfigAlias = joinerConfig.alias ?? []
const aliases = Array.isArray(joinerConfigAlias)
? joinerConfigAlias
: [joinerConfigAlias]
const entryPointAlias = aliases.find((alias) => {
const aliasNames = Array.isArray(alias.name) ? alias.name : [alias.name]
return aliasNames.includes(entryPoint)
return aliasNames.some((alias) => alias === entryPoint)
})
if (entryPointAlias) {
@@ -132,6 +153,35 @@ function retrieveJoinerConfigFromPropertyName({ entryPoint, joinerConfigs }) {
return {}
}
function findAliasFromJoinerConfig({
joinerConfig,
entryPoint,
}: {
joinerConfig: ModuleJoinerConfig
entryPoint: string
}) {
const joinerConfigAlias = joinerConfig.alias ?? []
const aliases = Array.isArray(joinerConfigAlias)
? joinerConfigAlias
: [joinerConfigAlias]
const entryPointAlias = aliases.find((alias) => {
const aliasNames = Array.isArray(alias.name) ? alias.name : [alias.name]
return aliasNames.some((alias) => alias === entryPoint)
})
if (entryPointAlias) {
joinerConfigMapCache.set(entryPoint, {
joinerConfig,
alias: entryPointAlias,
})
return { joinerConfig, alias: entryPointAlias }
}
return
}
function assignRemoteQueryObject({
entryPoint,
filterKey,