Fix(orchestrator): Joiner field alias (#6602)

This commit is contained in:
Carlos R. L. Rodrigues
2024-03-06 15:17:11 -03:00
committed by GitHub
parent fcb03d60ea
commit 8a946beb75
4 changed files with 202 additions and 63 deletions

View File

@@ -0,0 +1,5 @@
---
"@medusajs/orchestration": patch
---
Fix field alias nested fields

View File

@@ -94,6 +94,9 @@ medusaIntegrationTestRunner({
}, },
payment_collection: { payment_collection: {
fields: ["id"], fields: ["id"],
payment_sessions: {
fields: ["id"],
},
}, },
}, },
}) })
@@ -143,6 +146,7 @@ medusaIntegrationTestRunner({
region: expect.objectContaining({ id: region.id }), region: expect.objectContaining({ id: region.id }),
payment_collection: expect.objectContaining({ payment_collection: expect.objectContaining({
id: paymentCollection.id, id: paymentCollection.id,
payment_sessions: expect.arrayContaining([]),
}), }),
}), }),
]) ])

View File

@@ -656,7 +656,13 @@ describe("RemoteJoiner", () => {
products { products {
variant { variant {
user_shortcut(arg: 123) { user_shortcut(arg: 123) {
name
email email
products {
product {
handler
}
}
} }
} }
} }
@@ -669,13 +675,7 @@ describe("RemoteJoiner", () => {
[ [
{ {
service: "order", service: "order",
fieds: ["id", "product_user_alias", "products"], fieds: ["id", "products"],
},
],
[
{
service: "variantService",
fieds: ["user_shortcut", "id", "product_id"],
}, },
], ],
[ [
@@ -698,6 +698,12 @@ describe("RemoteJoiner", () => {
fieds: ["name", "id"], fieds: ["name", "id"],
}, },
], ],
[
{
service: "variantService",
fieds: ["id", "product_id"],
},
],
[ [
{ {
service: "product", service: "product",
@@ -707,7 +713,13 @@ describe("RemoteJoiner", () => {
[ [
{ {
service: "user", service: "user",
fieds: ["email", "id"], fieds: ["name", "email", "products", "id"],
},
],
[
{
service: "product",
fieds: ["handler", "id"],
}, },
], ],
]) ])
@@ -736,6 +748,22 @@ describe("RemoteJoiner", () => {
user_shortcut: { user_shortcut: {
email: "janedoe@example.com", email: "janedoe@example.com",
id: 2, id: 2,
name: "Jane Doe",
products: [
{
product_id: [101, 102],
product: [
{
handler: "product-1-handler",
id: 101,
},
{
handler: "product-2-handler",
id: 102,
},
],
},
],
}, },
}, },
}) })

View File

@@ -8,7 +8,7 @@ import {
RemoteNestedExpands, RemoteNestedExpands,
} from "@medusajs/types" } from "@medusajs/types"
import { isDefined, isString } from "@medusajs/utils" import { deduplicate, isDefined, isString } from "@medusajs/utils"
import GraphQLParser from "./graphql-ast" import GraphQLParser from "./graphql-ast"
const BASE_PATH = "_root" const BASE_PATH = "_root"
@@ -603,100 +603,80 @@ export class RemoteJoiner {
expands: RemoteJoinerQuery["expands"], expands: RemoteJoinerQuery["expands"],
implodeMapping: InternalImplodeMapping[] implodeMapping: InternalImplodeMapping[]
): Map<string, RemoteExpandProperty> { ): Map<string, RemoteExpandProperty> {
const aliasRealPathMap = new Map<string, string[]>()
const parsedExpands = new Map<string, any>() const parsedExpands = new Map<string, any>()
parsedExpands.set(BASE_PATH, initialService) parsedExpands.set(BASE_PATH, initialService)
let forwardArgumentsOnPath: string[] = [] const forwardArgumentsOnPath: string[] = []
for (const expand of expands || []) { for (const expand of expands || []) {
const properties = expand.property.split(".") const properties = expand.property.split(".")
let currentServiceConfig = serviceConfig
const currentPath: string[] = [] const currentPath: string[] = []
const currentAliasPath: string[] = []
let currentServiceConfig = serviceConfig
for (const prop of properties) { for (const prop of properties) {
const fieldAlias = currentServiceConfig.fieldAlias ?? {} const fieldAlias = currentServiceConfig.fieldAlias ?? {}
if (fieldAlias[prop]) { if (fieldAlias[prop]) {
const alias = fieldAlias[prop] as any const aliasPath = [BASE_PATH, ...currentPath, prop].join(".")
const path = isString(alias) ? alias : alias.path const lastServiceConfig = this.parseAlias({
const fullPath = [...new Set(currentPath.concat(path.split(".")))] aliasPath,
aliasRealPathMap,
forwardArgumentsOnPath = forwardArgumentsOnPath.concat( expands,
(alias?.forwardArgumentsOnPath || []).map( expand,
(forPath) =>
BASE_PATH + "." + currentPath.concat(forPath).join(".")
)
)
implodeMapping.push({
location: currentPath,
property: prop, property: prop,
path: fullPath, parsedExpands,
isList: !!serviceConfig.relationships?.find( currentServiceConfig,
(relationship) => relationship.alias === fullPath[0] currentPath,
)?.isList, implodeMapping,
forwardArgumentsOnPath,
}) })
const extMapping = expands as unknown[] currentAliasPath.push(prop)
const middlePath = path.split(".").slice(0, -1) currentServiceConfig = lastServiceConfig
let curMiddlePath = currentPath
for (const path of middlePath) {
curMiddlePath = curMiddlePath.concat(path)
extMapping.push({
args: expand.args,
property: curMiddlePath.join("."),
isAliasMapping: true,
})
}
extMapping.push({
...expand,
property: fullPath.join("."),
isAliasMapping: true,
})
continue continue
} }
const fullPath = [BASE_PATH, ...currentPath, prop].join(".") const fullPath = [BASE_PATH, ...currentPath, prop].join(".")
const fullAliasPath = [BASE_PATH, ...currentAliasPath, prop].join(".")
const relationship = currentServiceConfig.relationships?.find( const relationship = currentServiceConfig.relationships?.find(
(relation) => relation.alias === prop (relation) => relation.alias === prop
) )
let fields: string[] | undefined = const isCurrentProp =
fullPath === BASE_PATH + "." + expand.property fullPath === BASE_PATH + "." + expand.property ||
? expand.fields ?? [] fullAliasPath == BASE_PATH + "." + expand.property
: undefined
const args = let fields: string[] = isCurrentProp ? expand.fields ?? [] : []
fullPath === BASE_PATH + "." + expand.property const args = isCurrentProp ? expand.args : []
? expand.args
: undefined
if (relationship) { if (relationship) {
const parentExpand = const parentExpand =
parsedExpands.get([BASE_PATH, ...currentPath].join(".")) || query parsedExpands.get([BASE_PATH, ...currentPath].join(".")) || query
if (parentExpand) { if (parentExpand) {
const relField = relationship.inverse const parRelField = relationship.inverse
? relationship.primaryKey ? relationship.primaryKey
: relationship.foreignKey.split(".").pop()! : relationship.foreignKey.split(".").pop()!
parentExpand.fields ??= [] parentExpand.fields ??= []
parentExpand.fields = parentExpand.fields parentExpand.fields = parentExpand.fields
.concat(relField.split(",")) .concat(parRelField.split(","))
.filter((field) => field !== relationship.alias) .filter((field) => field !== relationship.alias)
parentExpand.fields = [...new Set(parentExpand.fields)] parentExpand.fields = deduplicate(parentExpand.fields)
if (fields) {
const relField = relationship.inverse const relField = relationship.inverse
? relationship.foreignKey.split(".").pop()! ? relationship.foreignKey.split(".").pop()!
: relationship.primaryKey : relationship.primaryKey
fields = fields.concat(relField.split(",")) fields = fields.concat(relField.split(","))
} }
}
currentServiceConfig = this.getServiceConfig( currentServiceConfig = this.getServiceConfig(
relationship.serviceName relationship.serviceName
@@ -711,7 +691,14 @@ export class RemoteJoiner {
const isAliasMapping = (expand as any).isAliasMapping const isAliasMapping = (expand as any).isAliasMapping
if (!parsedExpands.has(fullPath)) { if (!parsedExpands.has(fullPath)) {
const parentPath = [BASE_PATH, ...currentPath].join(".") let parentPath = [BASE_PATH, ...currentPath].join(".")
if (aliasRealPathMap.has(parentPath)) {
parentPath = aliasRealPathMap
.get(parentPath)!
.slice(0, -1)
.join(".")
}
parsedExpands.set(fullPath, { parsedExpands.set(fullPath, {
property: prop, property: prop,
@@ -732,18 +719,133 @@ export class RemoteJoiner {
if (forwardArgumentsOnPath.includes(fullPath) && args) { if (forwardArgumentsOnPath.includes(fullPath) && args) {
exp.args = (exp.args || []).concat(args) exp.args = (exp.args || []).concat(args)
} }
exp.isAliasMapping ??= isAliasMapping
if (fields) { if (fields) {
exp.fields = (exp.fields || []).concat(fields) exp.fields = deduplicate((exp.fields ?? []).concat(fields))
} }
} }
currentPath.push(prop) currentPath.push(prop)
currentAliasPath.push(prop)
} }
} }
return parsedExpands return parsedExpands
} }
private parseAlias({
aliasPath,
aliasRealPathMap,
expands,
expand,
property,
parsedExpands,
currentServiceConfig,
currentPath,
implodeMapping,
forwardArgumentsOnPath,
}) {
const serviceConfig = currentServiceConfig
const fieldAlias = currentServiceConfig.fieldAlias ?? {}
const alias = fieldAlias[property] as any
const path = isString(alias) ? alias : alias.path
const fullPath = [...currentPath.concat(path.split("."))]
if (aliasRealPathMap.has(aliasPath)) {
currentPath.push(...path.split("."))
const fullPath = [BASE_PATH, ...currentPath].join(".")
return parsedExpands.get(fullPath).serviceConfig
}
// remove alias from fields
const parentPath = [BASE_PATH, ...currentPath].join(".")
const parentExpands = parsedExpands.get(parentPath)
parentExpands.fields = parentExpands.fields.filter(
(field) => field !== property
)
forwardArgumentsOnPath.push(
...(alias?.forwardArgumentsOnPath || []).map(
(forPath) => BASE_PATH + "." + currentPath.concat(forPath).join(".")
)
)
implodeMapping.push({
location: [...currentPath],
property,
path: fullPath,
isList: !!serviceConfig.relationships?.find(
(relationship) => relationship.alias === fullPath[0]
)?.isList,
})
const extMapping = expands as unknown[]
const fullAliasProp = fullPath.join(".")
const middlePath = path.split(".")
let curMiddlePath = currentPath
for (const path of middlePath) {
curMiddlePath = curMiddlePath.concat(path)
const midProp = curMiddlePath.join(".")
const existingExpand = expands.find((exp) => exp.property === midProp)
const extraExtends = {
...(midProp === fullAliasProp ? expand : {}),
property: midProp,
isAliasMapping: !existingExpand,
}
if (forwardArgumentsOnPath.includes(BASE_PATH + "." + midProp)) {
extraExtends.args = (existingExpand?.args ?? []).concat(
expand?.args ?? []
)
}
extMapping.push(extraExtends)
}
const partialPath: string[] = []
for (const partial of path.split(".")) {
const relationship = currentServiceConfig.relationships?.find(
(relation) => relation.alias === partial
)
if (relationship) {
currentServiceConfig = this.getServiceConfig(relationship.serviceName)!
if (!currentServiceConfig) {
throw new Error(
`Target service not found: ${relationship.serviceName}`
)
}
}
const completePath = [
BASE_PATH,
...currentPath.concat(partialPath),
partial,
]
const parentPath = completePath.slice(0, -1).join(".")
partialPath.push(partial)
parsedExpands.set(completePath.join("."), {
property: partial,
serviceConfig: currentServiceConfig,
parent: parentPath,
parentConfig: parsedExpands.get(parentPath).serviceConfig,
})
}
currentPath.push(...path.split("."))
aliasRealPathMap.set(aliasPath, [BASE_PATH, ...currentPath])
return currentServiceConfig
}
private groupExpands( private groupExpands(
parsedExpands: Map<string, RemoteExpandProperty> parsedExpands: Map<string, RemoteExpandProperty>
): Map<string, RemoteExpandProperty> { ): Map<string, RemoteExpandProperty> {