feat(modules-sdk): remote query retrieve (#6849)

What:

Remote Joiner options to check if keys exist on entry points or relations
This commit is contained in:
Carlos R. L. Rodrigues
2024-03-29 09:26:24 +00:00
committed by GitHub
parent cbb5e6bd99
commit 1c6ba4468e
10 changed files with 356 additions and 34 deletions
@@ -129,6 +129,11 @@ export const mockServiceList = (serviceName) => {
})
}
// mock filtering on service order
if (serviceName === "orderService" && data.options?.id) {
resultset = resultset.filter((item) => data.options.id.includes(item.id))
}
return {
data: resultset,
path: serviceName === "productService" ? "rows" : undefined,
@@ -241,12 +241,7 @@ describe("RemoteJoiner", () => {
fields: ["name"],
},
],
args: [
{
name: "id",
value: "3",
},
],
args: [],
}
const data = await joiner.query(query)
@@ -802,4 +797,34 @@ describe("RemoteJoiner", () => {
`Service with alias "user" was not found.`
)
})
it("Should throw when any key of the entrypoint isn't found", async () => {
const query = RemoteJoiner.parseQuery(`
query {
order (id: 201) {
id
number
}
}
`)
const data = await joiner.query(query, {
throwIfKeyNotFound: true,
})
expect(data.length).toEqual(1)
const queryNotFound = RemoteJoiner.parseQuery(`
query {
order (id: "ord_1234556") {
id
number
}
}
`)
const dataNotFound = joiner.query(queryNotFound, {
throwIfKeyNotFound: true,
})
expect(dataNotFound).rejects.toThrowError("order id not found: ord_1234556")
})
})
@@ -569,19 +569,13 @@ describe("RemoteJoiner", () => {
fields: ["name"],
},
],
args: [
{
name: "id",
value: "3",
},
],
}
await joiner.query(query)
expect(serviceMock.orderService).toHaveBeenCalledTimes(1)
expect(serviceMock.orderService).toHaveBeenCalledWith({
args: [],
args: undefined,
fields: ["number", "date", "products", "user_id"],
expands: {
products: {
@@ -589,7 +583,7 @@ describe("RemoteJoiner", () => {
fields: ["product_id"],
},
},
options: { id: ["3"] },
options: { id: undefined },
})
expect(serviceMock.userService).toHaveBeenCalledTimes(1)
@@ -8,7 +8,8 @@ import {
RemoteNestedExpands,
} from "@medusajs/types"
import { deduplicate, isDefined, isString } from "@medusajs/utils"
import { RemoteJoinerOptions } from "@medusajs/types"
import { MedusaError, deduplicate, isDefined, isString } from "@medusajs/utils"
import GraphQLParser from "./graphql-ast"
const BASE_PATH = "_root"
@@ -331,7 +332,8 @@ export class RemoteJoiner {
expand: RemoteExpandProperty,
pkField: string,
ids?: (unknown | unknown[])[],
relationship?: any
relationship?: any,
options?: RemoteJoinerOptions
): Promise<{
data: unknown[] | { [path: string]: unknown }
path?: string
@@ -372,6 +374,15 @@ export class RemoteJoiner {
resData = Array.isArray(resData) ? resData : [resData]
this.checkIfKeysExist(
uniqueIds,
resData,
expand,
pkField,
relationship,
options
)
const filteredDataArray = resData.map((data: any) =>
RemoteJoiner.filterFields(data, expand.fields, expand.expands)
)
@@ -385,6 +396,47 @@ export class RemoteJoiner {
return response
}
private checkIfKeysExist(
uniqueIds: unknown[] | undefined,
resData: any[],
expand: RemoteExpandProperty,
pkField: string,
relationship?: any,
options?: RemoteJoinerOptions
) {
if (
!(
isDefined(uniqueIds) &&
((options?.throwIfKeyNotFound && !isDefined(relationship)) ||
(options?.throwIfRelationNotFound && isDefined(relationship)))
)
) {
return
}
if (isDefined(relationship)) {
if (
Array.isArray(options?.throwIfRelationNotFound) &&
!options?.throwIfRelationNotFound.includes(relationship.serviceName)
) {
return
}
}
const notFound = new Set(uniqueIds)
resData.forEach((data) => {
notFound.delete(data[pkField])
})
if (notFound.size > 0) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`${expand.serviceConfig.serviceName} ${pkField} not found: ` +
Array.from(notFound).join(", ")
)
}
}
private handleFieldAliases(
items: any[],
parsedExpands: Map<string, RemoteExpandProperty>,
@@ -466,7 +518,8 @@ export class RemoteJoiner {
private async handleExpands(
items: any[],
parsedExpands: Map<string, RemoteExpandProperty>,
implodeMapping: InternalImplodeMapping[] = []
implodeMapping: InternalImplodeMapping[] = [],
options?: RemoteJoinerOptions
): Promise<void> {
if (!parsedExpands) {
return
@@ -488,7 +541,12 @@ export class RemoteJoiner {
}
if (nestedItems.length > 0) {
await this.expandProperty(nestedItems, expand.parentConfig!, expand)
await this.expandProperty(
nestedItems,
expand.parentConfig!,
expand,
options
)
}
}
@@ -498,7 +556,8 @@ export class RemoteJoiner {
private async expandProperty(
items: any[],
parentServiceConfig: JoinerServiceConfig,
expand?: RemoteExpandProperty
expand?: RemoteExpandProperty,
options?: RemoteJoinerOptions
): Promise<void> {
if (!expand) {
return
@@ -509,14 +568,20 @@ export class RemoteJoiner {
)
if (relationship) {
await this.expandRelationshipProperty(items, expand, relationship)
await this.expandRelationshipProperty(
items,
expand,
relationship,
options
)
}
}
private async expandRelationshipProperty(
items: any[],
expand: RemoteExpandProperty,
relationship: JoinerRelationship
relationship: JoinerRelationship,
options?: RemoteJoinerOptions
): Promise<void> {
const field = relationship.inverse
? relationship.primaryKey
@@ -552,7 +617,8 @@ export class RemoteJoiner {
expand,
field,
idsToFetch,
relationship
relationship,
options
)
const joinFields = relationship.inverse
@@ -602,14 +668,16 @@ export class RemoteJoiner {
query: RemoteJoinerQuery,
serviceConfig: JoinerServiceConfig,
expands: RemoteJoinerQuery["expands"],
implodeMapping: InternalImplodeMapping[]
implodeMapping: InternalImplodeMapping[],
options?: RemoteJoinerOptions
): Map<string, RemoteExpandProperty> {
const parsedExpands = this.parseProperties(
initialService,
query,
serviceConfig,
expands,
implodeMapping
implodeMapping,
options
)
const groupedExpands = this.groupExpands(parsedExpands)
@@ -622,7 +690,8 @@ export class RemoteJoiner {
query: RemoteJoinerQuery,
serviceConfig: JoinerServiceConfig,
expands: RemoteJoinerQuery["expands"],
implodeMapping: InternalImplodeMapping[]
implodeMapping: InternalImplodeMapping[],
options?: RemoteJoinerOptions
): Map<string, RemoteExpandProperty> {
const aliasRealPathMap = new Map<string, string[]>()
const parsedExpands = new Map<string, any>()
@@ -913,7 +982,10 @@ export class RemoteJoiner {
return mergedExpands
}
async query(queryObj: RemoteJoinerQuery): Promise<any> {
async query(
queryObj: RemoteJoinerQuery,
options?: RemoteJoinerOptions
): Promise<any> {
const serviceConfig = this.getServiceConfig(
queryObj.service,
queryObj.alias
@@ -960,7 +1032,8 @@ export class RemoteJoiner {
root,
pkName,
primaryKeyArg?.value,
undefined
undefined,
options
)
const data = response.path ? response.data[response.path!] : response.data
@@ -968,7 +1041,8 @@ export class RemoteJoiner {
await this.handleExpands(
Array.isArray(data) ? data : [data],
parsedExpands,
implodeMapping
implodeMapping,
options
)
return response.data