feat: expand store product filtering (#973)
This commit is contained in:
1 parent
6dbd8d318d
commit
f61eaeec12
4 files changed
+590
-22
No files matched your search
@@ -4,9 +4,10 @@ const setupServer = require("../../../helpers/setup-server")
|
|||||||
const { useApi } = require("../../../helpers/use-api")
|
const { useApi } = require("../../../helpers/use-api")
|
||||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||||
|
|
||||||
const productSeeder = require("../../helpers/product-seeder")
|
const productSeeder = require("../../helpers/store-product-seeder")
|
||||||
const adminSeeder = require("../../helpers/admin-seeder")
|
const adminSeeder = require("../../helpers/admin-seeder")
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
describe("/store/products", () => {
|
describe("/store/products", () => {
|
||||||
let medusaProcess
|
let medusaProcess
|
||||||
let dbConnection
|
let dbConnection
|
||||||
@@ -23,6 +24,204 @@ describe("/store/products", () => {
|
|||||||
medusaProcess.kill()
|
medusaProcess.kill()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("GET /store/products", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
try {
|
||||||
|
await productSeeder(dbConnection)
|
||||||
|
await adminSeeder(dbConnection)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns a list of products in collection", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const notExpected = [
|
||||||
|
expect.objectContaining({ collection_id: "test-collection" }),
|
||||||
|
expect.objectContaining({ collection_id: "test-collection1" }),
|
||||||
|
]
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.get("/store/products?collection_id[]=test-collection2")
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.products).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "test-product_filtering_2",
|
||||||
|
collection_id: "test-collection2",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
for (const notExpect of notExpected) {
|
||||||
|
expect(response.data.products).toEqual(
|
||||||
|
expect.not.arrayContaining([notExpect])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns a list of products in with a given tag", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const notExpected = [expect.objectContaining({ id: "tag4" })]
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.get("/store/products?tags[]=tag3")
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.products).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "test-product_filtering_1",
|
||||||
|
collection_id: "test-collection1",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
for (const notExpect of notExpected) {
|
||||||
|
expect(response.data.products).toEqual(
|
||||||
|
expect.not.arrayContaining([notExpect])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns gift card product", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.get("/store/products?is_giftcard=true")
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.products.length).toEqual(1)
|
||||||
|
expect(response.data.products).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "giftcard",
|
||||||
|
is_giftcard: true,
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns non gift card products", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.get("/store/products?is_giftcard=false")
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(response.data.products).toEqual(
|
||||||
|
expect.not.arrayContaining([
|
||||||
|
expect.objectContaining({ is_giftcard: true }),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns product with tag", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const notExpected = [expect.objectContaining({ id: "tag4" })]
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.get("/store/products?tags[]=tag3")
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.products).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "test-product_filtering_1",
|
||||||
|
collection_id: "test-collection1",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
for (const notExpect of notExpected) {
|
||||||
|
expect(response.data.products).toEqual(
|
||||||
|
expect.not.arrayContaining([notExpect])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns a list of products in with a given handle", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const notExpected = [
|
||||||
|
expect.objectContaining({ handle: "test-product_filtering_1" }),
|
||||||
|
]
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.get("/store/products?handle=test-product_filtering_2")
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.products).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "test-product_filtering_2",
|
||||||
|
handle: "test-product_filtering_2",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
for (const notExpect of notExpected) {
|
||||||
|
expect(response.data.products).toEqual(
|
||||||
|
expect.not.arrayContaining([notExpect])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns only published products", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const notExpected = [
|
||||||
|
expect.objectContaining({ status: "proposed" }),
|
||||||
|
expect.objectContaining({ status: "draft" }),
|
||||||
|
expect.objectContaining({ status: "rejected" }),
|
||||||
|
]
|
||||||
|
|
||||||
|
const response = await api.get("/store/products").catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.products).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "giftcard",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "test-product_filtering_1",
|
||||||
|
collection_id: "test-collection1",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "test-product_filtering_2",
|
||||||
|
collection_id: "test-collection2",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
for (const notExpect of notExpected) {
|
||||||
|
expect(response.data.products).toEqual(
|
||||||
|
expect.not.arrayContaining([notExpect])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("/store/products/:id", () => {
|
describe("/store/products/:id", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,287 @@
|
|||||||
|
const {
|
||||||
|
ProductCollection,
|
||||||
|
ProductTag,
|
||||||
|
ProductType,
|
||||||
|
ProductOption,
|
||||||
|
Region,
|
||||||
|
Product,
|
||||||
|
ShippingProfile,
|
||||||
|
ProductVariant,
|
||||||
|
Image,
|
||||||
|
} = require("@medusajs/medusa")
|
||||||
|
|
||||||
|
module.exports = async (connection, data = {}) => {
|
||||||
|
const manager = connection.manager
|
||||||
|
|
||||||
|
const defaultProfile = await manager.findOne(ShippingProfile, {
|
||||||
|
type: "default",
|
||||||
|
})
|
||||||
|
|
||||||
|
const coll = manager.create(ProductCollection, {
|
||||||
|
id: "test-collection",
|
||||||
|
handle: "test-collection",
|
||||||
|
title: "Test collection",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(coll)
|
||||||
|
|
||||||
|
const coll1 = manager.create(ProductCollection, {
|
||||||
|
id: "test-collection1",
|
||||||
|
handle: "test-collection1",
|
||||||
|
title: "Test collection 1",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(coll1)
|
||||||
|
|
||||||
|
const coll2 = manager.create(ProductCollection, {
|
||||||
|
id: "test-collection2",
|
||||||
|
handle: "test-collection2",
|
||||||
|
title: "Test collection 2",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(coll2)
|
||||||
|
|
||||||
|
const tag = manager.create(ProductTag, {
|
||||||
|
id: "tag1",
|
||||||
|
value: "123",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(tag)
|
||||||
|
|
||||||
|
const tag3 = manager.create(ProductTag, {
|
||||||
|
id: "tag3",
|
||||||
|
value: "123",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(tag3)
|
||||||
|
|
||||||
|
const tag4 = manager.create(ProductTag, {
|
||||||
|
id: "tag4",
|
||||||
|
value: "123",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(tag4)
|
||||||
|
|
||||||
|
const type = manager.create(ProductType, {
|
||||||
|
id: "test-type",
|
||||||
|
value: "test-type",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(type)
|
||||||
|
|
||||||
|
const image = manager.create(Image, {
|
||||||
|
id: "test-image",
|
||||||
|
url: "test-image.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(image)
|
||||||
|
|
||||||
|
await manager.insert(Region, {
|
||||||
|
id: "test-region",
|
||||||
|
name: "Test Region",
|
||||||
|
currency_code: "usd",
|
||||||
|
tax_rate: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
const p = manager.create(Product, {
|
||||||
|
id: "test-product",
|
||||||
|
handle: "test-product",
|
||||||
|
title: "Test product",
|
||||||
|
profile_id: defaultProfile.id,
|
||||||
|
description: "test-product-description",
|
||||||
|
collection_id: "test-collection",
|
||||||
|
type: { id: "test-type", value: "test-type" },
|
||||||
|
tags: [
|
||||||
|
{ id: "tag1", value: "123" },
|
||||||
|
{ tag: "tag2", value: "456" },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
p.images = [image]
|
||||||
|
|
||||||
|
await manager.save(p)
|
||||||
|
|
||||||
|
await manager.save(ProductOption, {
|
||||||
|
id: "test-option",
|
||||||
|
title: "test-option",
|
||||||
|
product_id: "test-product",
|
||||||
|
})
|
||||||
|
|
||||||
|
const variant1 = await manager.create(ProductVariant, {
|
||||||
|
id: "test-variant",
|
||||||
|
inventory_quantity: 10,
|
||||||
|
title: "Test variant",
|
||||||
|
variant_rank: 0,
|
||||||
|
sku: "test-sku",
|
||||||
|
ean: "test-ean",
|
||||||
|
upc: "test-upc",
|
||||||
|
barcode: "test-barcode",
|
||||||
|
product_id: "test-product",
|
||||||
|
prices: [{ id: "test-price", currency_code: "usd", amount: 100 }],
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
id: "test-variant-option",
|
||||||
|
value: "Default variant",
|
||||||
|
option_id: "test-option",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(variant1)
|
||||||
|
|
||||||
|
const variant2 = await manager.create(ProductVariant, {
|
||||||
|
id: "test-variant_1",
|
||||||
|
inventory_quantity: 10,
|
||||||
|
title: "Test variant rank (1)",
|
||||||
|
variant_rank: 2,
|
||||||
|
sku: "test-sku1",
|
||||||
|
ean: "test-ean1",
|
||||||
|
upc: "test-upc1",
|
||||||
|
barcode: "test-barcode 1",
|
||||||
|
product_id: "test-product",
|
||||||
|
prices: [{ id: "test-price1", currency_code: "usd", amount: 100 }],
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
id: "test-variant-option-1",
|
||||||
|
value: "Default variant 1",
|
||||||
|
option_id: "test-option",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(variant2)
|
||||||
|
|
||||||
|
const variant3 = await manager.create(ProductVariant, {
|
||||||
|
id: "test-variant_2",
|
||||||
|
inventory_quantity: 10,
|
||||||
|
title: "Test variant rank (2)",
|
||||||
|
variant_rank: 1,
|
||||||
|
sku: "test-sku2",
|
||||||
|
ean: "test-ean2",
|
||||||
|
upc: "test-upc2",
|
||||||
|
product_id: "test-product",
|
||||||
|
prices: [{ id: "test-price2", currency_code: "usd", amount: 100 }],
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
id: "test-variant-option-2",
|
||||||
|
value: "Default variant 2",
|
||||||
|
option_id: "test-option",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(variant3)
|
||||||
|
|
||||||
|
const p1 = manager.create(Product, {
|
||||||
|
id: "test-product1",
|
||||||
|
handle: "test-product1",
|
||||||
|
title: "Test product1",
|
||||||
|
profile_id: defaultProfile.id,
|
||||||
|
description: "test-product-description1",
|
||||||
|
collection_id: "test-collection",
|
||||||
|
type: { id: "test-type", value: "test-type" },
|
||||||
|
tags: [
|
||||||
|
{ id: "tag1", value: "123" },
|
||||||
|
{ tag: "tag2", value: "456" },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(p1)
|
||||||
|
|
||||||
|
const variant4 = await manager.create(ProductVariant, {
|
||||||
|
id: "test-variant_3",
|
||||||
|
inventory_quantity: 10,
|
||||||
|
title: "Test variant rank (2)",
|
||||||
|
variant_rank: 1,
|
||||||
|
sku: "test-sku3",
|
||||||
|
ean: "test-ean3",
|
||||||
|
upc: "test-upc3",
|
||||||
|
product_id: "test-product1",
|
||||||
|
prices: [{ id: "test-price3", currency_code: "usd", amount: 100 }],
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
id: "test-variant-option-3",
|
||||||
|
value: "Default variant 3",
|
||||||
|
option_id: "test-option",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(variant4)
|
||||||
|
|
||||||
|
const variant5 = await manager.create(ProductVariant, {
|
||||||
|
id: "test-variant_4",
|
||||||
|
inventory_quantity: 10,
|
||||||
|
title: "Test variant rank (2)",
|
||||||
|
variant_rank: 0,
|
||||||
|
sku: "test-sku4",
|
||||||
|
ean: "test-ean4",
|
||||||
|
upc: "test-upc4",
|
||||||
|
product_id: "test-product1",
|
||||||
|
prices: [{ id: "test-price4", currency_code: "usd", amount: 100 }],
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
id: "test-variant-option-4",
|
||||||
|
value: "Default variant 4",
|
||||||
|
option_id: "test-option",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(variant5)
|
||||||
|
|
||||||
|
const product1 = manager.create(Product, {
|
||||||
|
id: "test-product_filtering_1",
|
||||||
|
handle: "test-product_filtering_1",
|
||||||
|
title: "Test product filtering 1",
|
||||||
|
profile_id: defaultProfile.id,
|
||||||
|
description: "test-product-description",
|
||||||
|
type: { id: "test-type", value: "test-type" },
|
||||||
|
collection_id: "test-collection1",
|
||||||
|
status: "published",
|
||||||
|
tags: [{ id: "tag3", value: "123" }],
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(product1)
|
||||||
|
|
||||||
|
const product2 = manager.create(Product, {
|
||||||
|
id: "test-product_filtering_2",
|
||||||
|
handle: "test-product_filtering_2",
|
||||||
|
title: "Test product filtering 2",
|
||||||
|
profile_id: defaultProfile.id,
|
||||||
|
description: "test-product-description",
|
||||||
|
type: { id: "test-type", value: "test-type" },
|
||||||
|
collection_id: "test-collection2",
|
||||||
|
status: "published",
|
||||||
|
tags: [{ id: "tag4", value: "1234" }],
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(product2)
|
||||||
|
|
||||||
|
const product3 = manager.create(Product, {
|
||||||
|
id: "test-product_filtering_3",
|
||||||
|
handle: "test-product_filtering_3",
|
||||||
|
title: "Test product filtering 3",
|
||||||
|
profile_id: defaultProfile.id,
|
||||||
|
description: "test-product-description",
|
||||||
|
type: { id: "test-type", value: "test-type" },
|
||||||
|
collection_id: "test-collection1",
|
||||||
|
status: "draft",
|
||||||
|
tags: [{ id: "tag4", value: "1234" }],
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(product3)
|
||||||
|
|
||||||
|
const gift_card = manager.create(Product, {
|
||||||
|
id: "giftcard",
|
||||||
|
handle: "giftcard",
|
||||||
|
is_giftcard: true,
|
||||||
|
title: "giftcard",
|
||||||
|
profile_id: defaultProfile.id,
|
||||||
|
description: "test-product-description",
|
||||||
|
type: { id: "test-type", value: "test-type" },
|
||||||
|
status: "published",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.save(gift_card)
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { IdMap } from "medusa-test-utils"
|
||||||
import { request } from "../../../../../helpers/test-request"
|
import { request } from "../../../../../helpers/test-request"
|
||||||
import { InviteServiceMock } from "../../../../../services/__mocks__/invite"
|
import { InviteServiceMock } from "../../../../../services/__mocks__/invite"
|
||||||
import { UserRole } from "../../../../../types/user"
|
import { UserRole } from "../../../../../types/user"
|
||||||
@@ -9,9 +10,9 @@ describe("POST /invites", () => {
|
|||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
subject = await request("POST", `/admin/invites`, {
|
subject = await request("POST", `/admin/invites`, {
|
||||||
payload: {
|
payload: {
|
||||||
role: "",
|
role: "admin",
|
||||||
},
|
},
|
||||||
session: {
|
adminSession: {
|
||||||
jwt: {
|
jwt: {
|
||||||
userId: "test_user",
|
userId: "test_user",
|
||||||
},
|
},
|
||||||
@@ -25,6 +26,10 @@ describe("POST /invites", () => {
|
|||||||
|
|
||||||
it("throws when role is empty", () => {
|
it("throws when role is empty", () => {
|
||||||
expect(subject.error).toBeTruthy()
|
expect(subject.error).toBeTruthy()
|
||||||
|
expect(subject.error.text).toEqual(
|
||||||
|
`{"type":"invalid_data","message":"user must be an email"}`
|
||||||
|
)
|
||||||
|
expect(subject.error.status).toEqual(400)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -37,9 +42,9 @@ describe("POST /invites", () => {
|
|||||||
role: "admin",
|
role: "admin",
|
||||||
user: "lebron@james.com",
|
user: "lebron@james.com",
|
||||||
},
|
},
|
||||||
session: {
|
adminSession: {
|
||||||
jwt: {
|
jwt: {
|
||||||
userId: "test_user",
|
userId: IdMap.getId("admin_user"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,14 +1,40 @@
|
|||||||
import { Type } from "class-transformer"
|
import { Transform, Type } from "class-transformer"
|
||||||
import { IsBoolean, IsInt, IsNumber, IsOptional } from "class-validator"
|
import {
|
||||||
|
IsArray,
|
||||||
|
IsBoolean,
|
||||||
|
IsNumber,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
ValidateNested,
|
||||||
|
} from "class-validator"
|
||||||
|
import { omit, pickBy, identity } from "lodash"
|
||||||
|
import { MedusaError } from "medusa-core-utils"
|
||||||
import { defaultStoreProductsRelations } from "."
|
import { defaultStoreProductsRelations } from "."
|
||||||
import { ProductService } from "../../../../services"
|
import { ProductService } from "../../../../services"
|
||||||
|
import { DateComparisonOperator } from "../../../../types/common"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
|
import { optionalBooleanMapper } from "../../../../utils/validators/is-boolean"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [get] /products
|
* @oas [get] /products
|
||||||
* operationId: GetProducts
|
* operationId: GetProducts
|
||||||
* summary: List Products
|
* summary: List Products
|
||||||
* description: "Retrieves a list of Products."
|
* description: "Retrieves a list of Products."
|
||||||
|
* parameters:
|
||||||
|
* - (query) q {string} Query used for searching products.
|
||||||
|
* - (query) id {string} Id of the product to search for.
|
||||||
|
* - (query) collection_id {string[]} Collection ids to search for.
|
||||||
|
* - (query) tags {string[]} Tags to search for.
|
||||||
|
* - (query) title {string} to search for.
|
||||||
|
* - (query) description {string} to search for.
|
||||||
|
* - (query) handle {string} to search for.
|
||||||
|
* - (query) is_giftcard {string} Search for giftcards using is_giftcard=true.
|
||||||
|
* - (query) type {string} to search for.
|
||||||
|
* - (query) created_at {DateComparisonOperator} Date comparison for when resulting products was created, i.e. less than, greater than etc.
|
||||||
|
* - (query) updated_at {DateComparisonOperator} Date comparison for when resulting products was updated, i.e. less than, greater than etc.
|
||||||
|
* - (query) deleted_at {DateComparisonOperator} Date comparison for when resulting products was deleted, i.e. less than, greater than etc.
|
||||||
|
* - (query) offset {string} How many products to skip in the result.
|
||||||
|
* - (query) limit {string} Limit the number of products returned.
|
||||||
* tags:
|
* tags:
|
||||||
* - Product
|
* - Product
|
||||||
* responses:
|
* responses:
|
||||||
@@ -37,13 +63,13 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
const validated = await validator(StoreGetProductsParams, req.query)
|
const validated = await validator(StoreGetProductsParams, req.query)
|
||||||
|
|
||||||
const selector = {}
|
const filterableFields: StoreGetProductsParams = omit(validated, [
|
||||||
|
"limit",
|
||||||
|
"offset",
|
||||||
|
])
|
||||||
|
|
||||||
if (validated.is_giftcard && validated.is_giftcard === true) {
|
// get only published products for store endpoint
|
||||||
selector["is_giftcard"] = validated.is_giftcard
|
filterableFields["status"] = ["published"]
|
||||||
}
|
|
||||||
|
|
||||||
selector["status"] = ["published"]
|
|
||||||
|
|
||||||
const listConfig = {
|
const listConfig = {
|
||||||
relations: defaultStoreProductsRelations,
|
relations: defaultStoreProductsRelations,
|
||||||
@@ -52,7 +78,7 @@ export default async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const [products, count] = await productService.listAndCount(
|
const [products, count] = await productService.listAndCount(
|
||||||
selector,
|
pickBy(filterableFields, (val) => typeof val !== "undefined"),
|
||||||
listConfig
|
listConfig
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -64,17 +90,68 @@ export default async (req, res) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StoreGetProductsParams {
|
export class StoreGetProductsPaginationParams {
|
||||||
@IsInt()
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
limit = 100
|
offset?: number = 0
|
||||||
|
|
||||||
@IsInt()
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
offset = 0
|
limit?: number = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
export class StoreGetProductsParams extends StoreGetProductsPaginationParams {
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
id?: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
q?: string
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsOptional()
|
||||||
|
collection_id?: string[]
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsOptional()
|
||||||
|
tags?: string[]
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
title?: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
description?: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
handle?: string
|
||||||
|
|
||||||
|
@IsBoolean()
|
||||||
|
@IsOptional()
|
||||||
|
@Transform(({ value }) => optionalBooleanMapper.get(value.toLowerCase()))
|
||||||
|
is_giftcard?: boolean
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
type?: string
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsBoolean()
|
@ValidateNested()
|
||||||
@Type(() => Boolean)
|
@Type(() => DateComparisonOperator)
|
||||||
is_giftcard?: boolean
|
created_at?: DateComparisonOperator
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => DateComparisonOperator)
|
||||||
|
updated_at?: DateComparisonOperator
|
||||||
|
|
||||||
|
@ValidateNested()
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => DateComparisonOperator)
|
||||||
|
deleted_at?: DateComparisonOperator
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user