Fix(orchestrator): Joiner field alias (#6602)
This commit is contained in:
committed by
GitHub
parent
fcb03d60ea
commit
8a946beb75
5
.changeset/quick-geckos-tie.md
Normal file
5
.changeset/quick-geckos-tie.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/orchestration": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix field alias nested fields
|
||||||
@@ -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([]),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -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,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
Reference in New Issue
Block a user