feat(medusa,utils): Add support for multiple where condition on the same column (#4046)

This commit is contained in:
Adrien de Peretti
2023-05-15 21:04:03 +02:00
committed by GitHub
parent a86f0e815a
commit cdbac2c840
5 changed files with 454 additions and 86 deletions
+6
View File
@@ -0,0 +1,6 @@
---
"@medusajs/medusa": patch
"@medusajs/utils": patch
---
feat(medusa, medusa-utils): Add support for multiple where condition on the same column
@@ -1,5 +1,18 @@
import { FindOptionsOrder, FindOptionsSelect, In, MoreThan, Not } from "typeorm" import {
import { addOrderToSelect, buildLegacyFieldsListFrom, buildQuery } from "../build-query" And,
FindOptionsOrder,
FindOptionsSelect,
In,
LessThanOrEqual,
MoreThan,
MoreThanOrEqual,
Not,
} from "typeorm"
import {
addOrderToSelect,
buildLegacyFieldsListFrom,
buildQuery,
} from "../build-query"
describe("buildQuery", () => { describe("buildQuery", () => {
it("successfully creates query", () => { it("successfully creates query", () => {
@@ -13,8 +26,12 @@ describe("buildQuery", () => {
date: { gt: date }, date: { gt: date },
amount: { gt: 10 }, amount: { gt: 10 },
rule: { rule: {
type: "fixed" type: "fixed",
} },
updated_at: {
gte: "value",
lte: "value",
},
}, },
{ {
select: [ select: [
@@ -57,8 +74,8 @@ describe("buildQuery", () => {
order: { order: {
id: "ASC", id: "ASC",
"items.id": "ASC", "items.id": "ASC",
"items.variant.id": "ASC" "items.variant.id": "ASC",
} },
} }
) )
@@ -70,8 +87,9 @@ describe("buildQuery", () => {
date: MoreThan(date), date: MoreThan(date),
amount: MoreThan(10), amount: MoreThan(10),
rule: { rule: {
type: "fixed" type: "fixed",
} },
updated_at: And(MoreThanOrEqual("value"), LessThanOrEqual("value")),
}, },
select: { select: {
order: { order: {
@@ -120,21 +138,21 @@ describe("buildQuery", () => {
}, },
items: { items: {
variants: { variants: {
product: true product: true,
}, },
tax_lines: true, tax_lines: true,
adjustments: true adjustments: true,
} },
}, },
order: { order: {
id: "ASC", id: "ASC",
items: { items: {
id: "ASC", id: "ASC",
variant: { variant: {
id: "ASC" id: "ASC",
} },
} },
} },
}) })
}) })
}) })
@@ -166,22 +184,24 @@ describe("buildLegacyFieldsListFrom", () => {
}) })
expect(q.length).toBe(14) expect(q.length).toBe(14)
expect(q).toEqual(expect.arrayContaining([ expect(q).toEqual(
"order", expect.arrayContaining([
"order.items", "order",
"order.swaps", "order.items",
"order.swaps.additional_items", "order.swaps",
"order.discounts", "order.swaps.additional_items",
"order.discounts.rule", "order.discounts",
"order.claims", "order.discounts.rule",
"order.claims.additional_items", "order.claims",
"additional_items", "order.claims.additional_items",
"additional_items.variant", "additional_items",
"return_order", "additional_items.variant",
"return_order.items", "return_order",
"return_order.shipping_method", "return_order.items",
"return_order.shipping_method.tax_lines", "return_order.shipping_method",
])) "return_order.shipping_method.tax_lines",
])
)
}) })
it("successfully build back relation object shape to list", () => { it("successfully build back relation object shape to list", () => {
@@ -209,35 +229,37 @@ describe("buildLegacyFieldsListFrom", () => {
}, },
items: { items: {
variants: { variants: {
product: true product: true,
}, },
tax_lines: true, tax_lines: true,
adjustments: true adjustments: true,
} },
}) })
expect(q.length).toBe(19) expect(q.length).toBe(19)
expect(q).toEqual(expect.arrayContaining([ expect(q).toEqual(
"order", expect.arrayContaining([
"order.items", "order",
"order.swaps", "order.items",
"order.swaps.additional_items", "order.swaps",
"order.discounts", "order.swaps.additional_items",
"order.discounts.rule", "order.discounts",
"order.claims", "order.discounts.rule",
"order.claims.additional_items", "order.claims",
"additional_items", "order.claims.additional_items",
"additional_items.variant", "additional_items",
"return_order", "additional_items.variant",
"return_order.items", "return_order",
"return_order.shipping_method", "return_order.items",
"return_order.shipping_method.tax_lines", "return_order.shipping_method",
"items.variants", "return_order.shipping_method.tax_lines",
"items.variants.product", "items.variants",
"items", "items.variants.product",
"items.tax_lines", "items",
"items.adjustments", "items.tax_lines",
])) "items.adjustments",
])
)
}) })
it("successfully build back order object shape to list", () => { it("successfully build back order object shape to list", () => {
@@ -246,37 +268,39 @@ describe("buildLegacyFieldsListFrom", () => {
items: { items: {
id: "ASC", id: "ASC",
variant: { variant: {
id: "ASC" id: "ASC",
} },
} },
}) })
expect(q.length).toBe(5) expect(q.length).toBe(5)
expect(q).toEqual(expect.arrayContaining([ expect(q).toEqual(
"id", expect.arrayContaining([
"items", "id",
"items.id", "items",
"items.variant", "items.id",
"items.variant.id" "items.variant",
])) "items.variant.id",
])
)
}) })
describe('addOrderToSelect', function () { describe("addOrderToSelect", function () {
it("successfully add the order fields to the select object", () => { it("successfully add the order fields to the select object", () => {
const select: FindOptionsSelect<any> = { const select: FindOptionsSelect<any> = {
item: { item: {
variant: { variant: {
id: true id: true,
} },
} },
} }
const order: FindOptionsOrder<any> = { const order: FindOptionsOrder<any> = {
item: { item: {
variant: { variant: {
rank: "ASC" rank: "ASC",
} },
} },
} }
addOrderToSelect(order, select) addOrderToSelect(order, select)
@@ -285,10 +309,10 @@ describe("buildLegacyFieldsListFrom", () => {
item: { item: {
variant: { variant: {
id: true, id: true,
rank: true rank: true,
} },
} },
}) })
}) })
}); })
}) })
+16 -4
View File
@@ -1,4 +1,5 @@
import { import {
And,
FindManyOptions, FindManyOptions,
FindOperator, FindOperator,
FindOptionsRelations, FindOptionsRelations,
@@ -105,18 +106,19 @@ function buildWhere<TWhereKeys extends object, TEntity>(
if (typeof value === "object") { if (typeof value === "object") {
Object.entries(value).forEach(([objectKey, objectValue]) => { Object.entries(value).forEach(([objectKey, objectValue]) => {
where[key] = where[key] || []
switch (objectKey) { switch (objectKey) {
case "lt": case "lt":
where[key] = LessThan(objectValue) where[key].push(LessThan(objectValue))
break break
case "gt": case "gt":
where[key] = MoreThan(objectValue) where[key].push(MoreThan(objectValue))
break break
case "lte": case "lte":
where[key] = LessThanOrEqual(objectValue) where[key].push(LessThanOrEqual(objectValue))
break break
case "gte": case "gte":
where[key] = MoreThanOrEqual(objectValue) where[key].push(MoreThanOrEqual(objectValue))
break break
default: default:
if (objectValue != undefined && typeof objectValue === "object") { if (objectValue != undefined && typeof objectValue === "object") {
@@ -128,6 +130,16 @@ function buildWhere<TWhereKeys extends object, TEntity>(
return return
}) })
if (!Array.isArray(where[key])) {
continue
}
if (where[key].length === 1) {
where[key] = where[key][0]
} else {
where[key] = And(...where[key])
}
continue continue
} }
@@ -0,0 +1,318 @@
import {
And,
FindOptionsOrder,
FindOptionsSelect,
In,
LessThanOrEqual,
MoreThan,
MoreThanOrEqual,
Not,
} from "typeorm"
import {
addOrderToSelect,
buildQuery,
objectToStringPath,
} from "../build-query"
describe("buildQuery", () => {
it("successfully creates query", () => {
const date = new Date()
const q = buildQuery(
{
id: "1234",
test1: ["123", "12", "1"],
test2: Not("this"),
date: { gt: date },
amount: { gt: 10 },
rule: {
type: "fixed",
},
updated_at: {
gte: "value",
lte: "value",
},
},
{
select: [
"order",
"order.items",
"order.swaps",
"order.swaps.additional_items",
"order.discounts",
"order.discounts.rule",
"order.claims",
"order.claims.additional_items",
"additional_items",
"additional_items.variant",
"return_order",
"return_order.items",
"return_order.shipping_method",
"return_order.shipping_method.tax_lines",
],
relations: [
"order",
"order.items",
"order.swaps",
"order.swaps.additional_items",
"order.discounts",
"order.discounts.rule",
"order.claims",
"order.claims.additional_items",
"additional_items",
"additional_items.variant",
"return_order",
"return_order.items",
"return_order.shipping_method",
"return_order.shipping_method.tax_lines",
"items.variants",
"items.variants.product",
"items",
"items.tax_lines",
"items.adjustments",
],
order: {
id: "ASC",
"items.id": "ASC",
"items.variant.id": "ASC",
},
}
)
expect(q).toEqual({
where: {
id: "1234",
test1: In(["123", "12", "1"]),
test2: Not("this"),
date: MoreThan(date),
amount: MoreThan(10),
rule: {
type: "fixed",
},
updated_at: And(MoreThanOrEqual("value"), LessThanOrEqual("value")),
},
select: {
order: {
items: true,
swaps: {
additional_items: true,
},
discounts: {
rule: true,
},
claims: {
additional_items: true,
},
},
additional_items: {
variant: true,
},
return_order: {
items: true,
shipping_method: {
tax_lines: true,
},
},
},
relations: {
order: {
items: true,
swaps: {
additional_items: true,
},
discounts: {
rule: true,
},
claims: {
additional_items: true,
},
},
additional_items: {
variant: true,
},
return_order: {
items: true,
shipping_method: {
tax_lines: true,
},
},
items: {
variants: {
product: true,
},
tax_lines: true,
adjustments: true,
},
},
order: {
id: "ASC",
items: {
id: "ASC",
variant: {
id: "ASC",
},
},
},
})
})
})
describe("objectToStringPath", () => {
it("successfully build back select object shape to list", () => {
const q = objectToStringPath({
order: {
items: true,
swaps: {
additional_items: true,
},
discounts: {
rule: true,
},
claims: {
additional_items: true,
},
},
additional_items: {
variant: true,
},
return_order: {
items: true,
shipping_method: {
tax_lines: true,
},
},
})
expect(q.length).toBe(14)
expect(q).toEqual(
expect.arrayContaining([
"order",
"order.items",
"order.swaps",
"order.swaps.additional_items",
"order.discounts",
"order.discounts.rule",
"order.claims",
"order.claims.additional_items",
"additional_items",
"additional_items.variant",
"return_order",
"return_order.items",
"return_order.shipping_method",
"return_order.shipping_method.tax_lines",
])
)
})
it("successfully build back relation object shape to list", () => {
const q = objectToStringPath({
order: {
items: true,
swaps: {
additional_items: true,
},
discounts: {
rule: true,
},
claims: {
additional_items: true,
},
},
additional_items: {
variant: true,
},
return_order: {
items: true,
shipping_method: {
tax_lines: true,
},
},
items: {
variants: {
product: true,
},
tax_lines: true,
adjustments: true,
},
})
expect(q.length).toBe(19)
expect(q).toEqual(
expect.arrayContaining([
"order",
"order.items",
"order.swaps",
"order.swaps.additional_items",
"order.discounts",
"order.discounts.rule",
"order.claims",
"order.claims.additional_items",
"additional_items",
"additional_items.variant",
"return_order",
"return_order.items",
"return_order.shipping_method",
"return_order.shipping_method.tax_lines",
"items.variants",
"items.variants.product",
"items",
"items.tax_lines",
"items.adjustments",
])
)
})
it("successfully build back order object shape to list", () => {
const q = objectToStringPath({
id: "ASC",
items: {
id: "ASC",
variant: {
id: "ASC",
},
},
})
expect(q.length).toBe(5)
expect(q).toEqual(
expect.arrayContaining([
"id",
"items",
"items.id",
"items.variant",
"items.variant.id",
])
)
})
describe("addOrderToSelect", function () {
it("successfully add the order fields to the select object", () => {
const select: FindOptionsSelect<any> = {
item: {
variant: {
id: true,
},
},
}
const order: FindOptionsOrder<any> = {
item: {
variant: {
rank: "ASC",
},
},
}
addOrderToSelect(order, select)
expect(select).toEqual({
item: {
variant: {
id: true,
rank: true,
},
},
})
})
})
})
+14 -6
View File
@@ -1,5 +1,6 @@
import { ExtendedFindConfig, FindConfig } from "@medusajs/types" import { ExtendedFindConfig, FindConfig } from "@medusajs/types"
import { import {
And,
FindManyOptions, FindManyOptions,
FindOperator, FindOperator,
FindOptionsRelations, FindOptionsRelations,
@@ -105,29 +106,36 @@ function buildWhere<TWhereKeys extends object, TEntity>(
if (typeof value === "object") { if (typeof value === "object") {
Object.entries(value).forEach(([objectKey, objectValue]) => { Object.entries(value).forEach(([objectKey, objectValue]) => {
where[key] = where[key] || []
switch (objectKey) { switch (objectKey) {
case "lt": case "lt":
where[key] = LessThan(objectValue) where[key].push(LessThan(objectValue))
break break
case "gt": case "gt":
where[key] = MoreThan(objectValue) where[key].push(MoreThan(objectValue))
break break
case "lte": case "lte":
where[key] = LessThanOrEqual(objectValue) where[key].push(LessThanOrEqual(objectValue))
break break
case "gte": case "gte":
where[key] = MoreThanOrEqual(objectValue) where[key].push(MoreThanOrEqual(objectValue))
break break
default: default:
if (objectValue != undefined && typeof objectValue === "object") { if (objectValue != undefined && typeof objectValue === "object") {
where[key] = buildWhere<any, TEntity>(objectValue) where[key].push(buildWhere<any, TEntity>(objectValue))
return return
} }
where[key] = value where[key].push(value)
} }
return return
}) })
if (where[key].length === 1) {
where[key] = where[key][0]
} else {
where[key] = And(...where[key])
}
continue continue
} }