chore: fix interfaces for product module (#5387)
Some changes based on @shahednasser's PR - https://github.com/medusajs/medusa/pull/5341
This commit is contained in:
1 parent
a0963f0edf
commit
453297f525
8 files changed
+280
-152
No files matched your search
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/product": patch
|
||||||
|
"@medusajs/types": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
chore(product,types): fix interfaces for product module
|
||||||
+164
-88
@@ -1,12 +1,11 @@
|
|||||||
import { IProductModuleService } from "@medusajs/types"
|
import { IProductModuleService, ProductTypes } from "@medusajs/types"
|
||||||
import { Product, ProductCollection } from "@models"
|
|
||||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
import { ProductTypes } from "@medusajs/types"
|
import { Product, ProductCollection } from "@models"
|
||||||
|
|
||||||
import { initialize } from "../../../../src"
|
import { initialize } from "../../../../src"
|
||||||
import { DB_URL, TestDatabase } from "../../../utils"
|
|
||||||
import { createCollections } from "../../../__fixtures__/product"
|
|
||||||
import { EventBusService } from "../../../__fixtures__/event-bus"
|
import { EventBusService } from "../../../__fixtures__/event-bus"
|
||||||
|
import { createCollections } from "../../../__fixtures__/product"
|
||||||
|
import { DB_URL, TestDatabase } from "../../../utils"
|
||||||
|
|
||||||
describe("ProductModuleService product collections", () => {
|
describe("ProductModuleService product collections", () => {
|
||||||
let service: IProductModuleService
|
let service: IProductModuleService
|
||||||
@@ -24,14 +23,17 @@ describe("ProductModuleService product collections", () => {
|
|||||||
repositoryManager = await TestDatabase.forkManager()
|
repositoryManager = await TestDatabase.forkManager()
|
||||||
eventBus = new EventBusService()
|
eventBus = new EventBusService()
|
||||||
|
|
||||||
service = await initialize({
|
service = await initialize(
|
||||||
database: {
|
{
|
||||||
clientUrl: DB_URL,
|
database: {
|
||||||
schema: process.env.MEDUSA_PRODUCT_DB_SCHEMA,
|
clientUrl: DB_URL,
|
||||||
|
schema: process.env.MEDUSA_PRODUCT_DB_SCHEMA,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}, {
|
{
|
||||||
eventBusModuleService: eventBus
|
eventBusModuleService: eventBus,
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
testManager = await TestDatabase.forkManager()
|
testManager = await TestDatabase.forkManager()
|
||||||
|
|
||||||
@@ -47,15 +49,18 @@ describe("ProductModuleService product collections", () => {
|
|||||||
status: ProductTypes.ProductStatus.PUBLISHED,
|
status: ProductTypes.ProductStatus.PUBLISHED,
|
||||||
})
|
})
|
||||||
|
|
||||||
const productCollectionsData = [{
|
const productCollectionsData = [
|
||||||
id: "test-1",
|
{
|
||||||
title: "collection 1",
|
id: "test-1",
|
||||||
products: [productOne],
|
title: "collection 1",
|
||||||
},{
|
products: [productOne],
|
||||||
id: "test-2",
|
},
|
||||||
title: "collection",
|
{
|
||||||
products: [productTwo],
|
id: "test-2",
|
||||||
}]
|
title: "collection",
|
||||||
|
products: [productTwo],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
productCollections = await createCollections(
|
productCollections = await createCollections(
|
||||||
testManager,
|
testManager,
|
||||||
@@ -65,7 +70,10 @@ describe("ProductModuleService product collections", () => {
|
|||||||
productCollectionOne = productCollections[0]
|
productCollectionOne = productCollections[0]
|
||||||
productCollectionTwo = productCollections[1]
|
productCollectionTwo = productCollections[1]
|
||||||
|
|
||||||
await testManager.persistAndFlush([productCollectionOne, productCollectionTwo])
|
await testManager.persistAndFlush([
|
||||||
|
productCollectionOne,
|
||||||
|
productCollectionTwo,
|
||||||
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@@ -130,7 +138,7 @@ describe("ProductModuleService product collections", () => {
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: "product-1",
|
id: "product-1",
|
||||||
title: "product 1",
|
title: "product 1",
|
||||||
})
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
@@ -198,10 +206,12 @@ describe("ProductModuleService product collections", () => {
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: "test-1",
|
id: "test-1",
|
||||||
title: "collection 1",
|
title: "collection 1",
|
||||||
products: [expect.objectContaining({
|
products: [
|
||||||
id: "product-1",
|
expect.objectContaining({
|
||||||
title: "product 1",
|
id: "product-1",
|
||||||
})],
|
title: "product 1",
|
||||||
|
}),
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
@@ -215,28 +225,27 @@ describe("ProductModuleService product collections", () => {
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: "test-1",
|
id: "test-1",
|
||||||
title: "collection 1",
|
title: "collection 1",
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should return requested attributes when requested through config", async () => {
|
it("should return requested attributes when requested through config", async () => {
|
||||||
const result = await service.retrieveCollection(
|
const result = await service.retrieveCollection(productCollectionOne.id, {
|
||||||
productCollectionOne.id,
|
select: ["id", "title", "products.title"],
|
||||||
{
|
relations: ["products"],
|
||||||
select: ["id", "title", "products.title"],
|
})
|
||||||
relations: ["products"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(result).toEqual(
|
expect(result).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: "test-1",
|
id: "test-1",
|
||||||
title: "collection 1",
|
title: "collection 1",
|
||||||
products: [expect.objectContaining({
|
products: [
|
||||||
id: "product-1",
|
expect.objectContaining({
|
||||||
title: "product 1",
|
id: "product-1",
|
||||||
})],
|
title: "product 1",
|
||||||
}),
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -249,7 +258,9 @@ describe("ProductModuleService product collections", () => {
|
|||||||
error = e
|
error = e
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(error.message).toEqual("ProductCollection with id: does-not-exist was not found")
|
expect(error.message).toEqual(
|
||||||
|
"ProductCollection with id: does-not-exist was not found"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -257,28 +268,26 @@ describe("ProductModuleService product collections", () => {
|
|||||||
const collectionId = "test-1"
|
const collectionId = "test-1"
|
||||||
|
|
||||||
it("should delete the product collection given an ID successfully", async () => {
|
it("should delete the product collection given an ID successfully", async () => {
|
||||||
await service.deleteCollections(
|
await service.deleteCollections([collectionId])
|
||||||
[collectionId],
|
|
||||||
)
|
|
||||||
|
|
||||||
const collections = await service.listCollections({
|
const collections = await service.listCollections({
|
||||||
id: collectionId
|
id: collectionId,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(collections).toHaveLength(0)
|
expect(collections).toHaveLength(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should emit events through event bus", async () => {
|
it("should emit events through event bus", async () => {
|
||||||
const eventBusSpy = jest.spyOn(EventBusService.prototype, 'emit')
|
const eventBusSpy = jest.spyOn(EventBusService.prototype, "emit")
|
||||||
await service.deleteCollections(
|
await service.deleteCollections([collectionId])
|
||||||
[collectionId],
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith([{
|
expect(eventBusSpy).toHaveBeenCalledWith([
|
||||||
eventName: "product-collection.deleted",
|
{
|
||||||
data: { id: collectionId }
|
eventName: "product-collection.deleted",
|
||||||
}])
|
data: { id: collectionId },
|
||||||
|
},
|
||||||
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -286,35 +295,64 @@ describe("ProductModuleService product collections", () => {
|
|||||||
const collectionId = "test-1"
|
const collectionId = "test-1"
|
||||||
|
|
||||||
it("should emit events through event bus", async () => {
|
it("should emit events through event bus", async () => {
|
||||||
const eventBusSpy = jest.spyOn(EventBusService.prototype, 'emit')
|
const eventBusSpy = jest.spyOn(EventBusService.prototype, "emit")
|
||||||
|
|
||||||
await service.updateCollections(
|
await service.updateCollections([
|
||||||
[{
|
{
|
||||||
id: collectionId,
|
id: collectionId,
|
||||||
title: "New Collection"
|
title: "New Collection",
|
||||||
}]
|
},
|
||||||
)
|
])
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith([{
|
expect(eventBusSpy).toHaveBeenCalledWith([
|
||||||
eventName: "product-collection.updated",
|
{
|
||||||
data: { id: collectionId }
|
eventName: "product-collection.updated",
|
||||||
}])
|
data: { id: collectionId },
|
||||||
|
},
|
||||||
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should update the value of the collection successfully", async () => {
|
it("should update the value of the collection successfully", async () => {
|
||||||
await service.updateCollections(
|
await service.updateCollections([
|
||||||
[{
|
{
|
||||||
id: collectionId,
|
id: collectionId,
|
||||||
title: "New Collection"
|
title: "New Collection",
|
||||||
}]
|
},
|
||||||
)
|
])
|
||||||
|
|
||||||
const productCollection = await service.retrieveCollection(collectionId)
|
const productCollection = await service.retrieveCollection(collectionId)
|
||||||
|
|
||||||
expect(productCollection.title).toEqual("New Collection")
|
expect(productCollection.title).toEqual("New Collection")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should add products to a collection successfully", async () => {
|
||||||
|
await service.updateCollections([
|
||||||
|
{
|
||||||
|
id: collectionId,
|
||||||
|
product_ids: [productOne.id, productTwo.id],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const productCollection = await service.retrieveCollection(collectionId, {
|
||||||
|
select: ["products.id"],
|
||||||
|
relations: ["products"],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(productCollection).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
products: [
|
||||||
|
expect.objectContaining({
|
||||||
|
id: productOne.id,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: productTwo.id,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it("should throw an error when an id does not exist", async () => {
|
it("should throw an error when an id does not exist", async () => {
|
||||||
let error
|
let error
|
||||||
|
|
||||||
@@ -322,47 +360,85 @@ describe("ProductModuleService product collections", () => {
|
|||||||
await service.updateCollections([
|
await service.updateCollections([
|
||||||
{
|
{
|
||||||
id: "does-not-exist",
|
id: "does-not-exist",
|
||||||
title: "New Collection"
|
title: "New Collection",
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e
|
error = e
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(error.message).toEqual('ProductCollection with id "does-not-exist" not found')
|
expect(error.message).toEqual(
|
||||||
|
'ProductCollection with id "does-not-exist" not found'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("createCollections", () => {
|
describe("createCollections", () => {
|
||||||
it("should create a collection successfully", async () => {
|
it("should create a collection successfully", async () => {
|
||||||
const res = await service.createCollections(
|
const res = await service.createCollections([
|
||||||
[{
|
{
|
||||||
title: "New Collection"
|
title: "New Collection",
|
||||||
}]
|
},
|
||||||
)
|
])
|
||||||
|
|
||||||
const [productCollection] = await service.listCollections({
|
const [productCollection] = await service.listCollections({
|
||||||
title: "New Collection"
|
title: "New Collection",
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(productCollection.title).toEqual("New Collection")
|
expect(productCollection.title).toEqual("New Collection")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should emit events through event bus", async () => {
|
it("should create collection with products successfully", async () => {
|
||||||
const eventBusSpy = jest.spyOn(EventBusService.prototype, 'emit')
|
await service.createCollections([
|
||||||
|
{
|
||||||
|
title: "New Collection with products",
|
||||||
|
handle: "new-collection-with-products",
|
||||||
|
product_ids: [productOne.id, productTwo.id],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
const collections = await service.createCollections(
|
const [productCollection] = await service.listCollections(
|
||||||
[{
|
{
|
||||||
title: "New Collection"
|
handle: "new-collection-with-products",
|
||||||
}]
|
},
|
||||||
|
{
|
||||||
|
select: ["title", "handle", "products.id"],
|
||||||
|
relations: ["products"],
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
expect(productCollection).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
title: "New Collection with products",
|
||||||
|
handle: "new-collection-with-products",
|
||||||
|
products: [
|
||||||
|
expect.objectContaining({
|
||||||
|
id: productOne.id,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: productTwo.id,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should emit events through event bus", async () => {
|
||||||
|
const eventBusSpy = jest.spyOn(EventBusService.prototype, "emit")
|
||||||
|
|
||||||
|
const collections = await service.createCollections([
|
||||||
|
{
|
||||||
|
title: "New Collection",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith([{
|
expect(eventBusSpy).toHaveBeenCalledWith([
|
||||||
eventName: "product-collection.created",
|
{
|
||||||
data: { id: collections[0].id }
|
eventName: "product-collection.created",
|
||||||
}])
|
data: { id: collections[0].id },
|
||||||
|
},
|
||||||
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
+61
-46
@@ -1,9 +1,8 @@
|
|||||||
|
import { IProductModuleService, ProductTypes } from "@medusajs/types"
|
||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
import { Product, ProductOption } from "@models"
|
||||||
import { initialize } from "../../../../src"
|
import { initialize } from "../../../../src"
|
||||||
import { DB_URL, TestDatabase } from "../../../utils"
|
import { DB_URL, TestDatabase } from "../../../utils"
|
||||||
import { IProductModuleService } from "@medusajs/types"
|
|
||||||
import { Product, ProductOption } from "@models"
|
|
||||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
|
||||||
import { ProductTypes } from "@medusajs/types"
|
|
||||||
|
|
||||||
describe("ProductModuleService product options", () => {
|
describe("ProductModuleService product options", () => {
|
||||||
let service: IProductModuleService
|
let service: IProductModuleService
|
||||||
@@ -103,7 +102,7 @@ describe("ProductModuleService product options", () => {
|
|||||||
{
|
{
|
||||||
select: ["title", "product.id"],
|
select: ["title", "product.id"],
|
||||||
relations: ["product"],
|
relations: ["product"],
|
||||||
take: 1
|
take: 1,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -150,12 +149,13 @@ describe("ProductModuleService product options", () => {
|
|||||||
id: optionOne.id,
|
id: optionOne.id,
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
;[options, count] = await service.listAndCountOptions({}, { take: 1 })
|
;[options, count] = await service.listAndCountOptions({}, { take: 1 })
|
||||||
|
|
||||||
expect(count).toEqual(2)
|
expect(count).toEqual(2)
|
||||||
|
;[options, count] = await service.listAndCountOptions(
|
||||||
;[options, count] = await service.listAndCountOptions({}, { take: 1, skip: 1 })
|
{},
|
||||||
|
{ take: 1, skip: 1 }
|
||||||
|
)
|
||||||
|
|
||||||
expect(count).toEqual(2)
|
expect(count).toEqual(2)
|
||||||
expect(options).toEqual([
|
expect(options).toEqual([
|
||||||
@@ -173,19 +173,21 @@ describe("ProductModuleService product options", () => {
|
|||||||
{
|
{
|
||||||
select: ["title", "product.id"],
|
select: ["title", "product.id"],
|
||||||
relations: ["product"],
|
relations: ["product"],
|
||||||
take: 1
|
take: 1,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(count).toEqual(1)
|
expect(count).toEqual(1)
|
||||||
expect(options).toEqual([{
|
expect(options).toEqual([
|
||||||
id: optionOne.id,
|
{
|
||||||
title: optionOne.title,
|
id: optionOne.id,
|
||||||
product_id: productOne.id,
|
title: optionOne.title,
|
||||||
product: {
|
product_id: productOne.id,
|
||||||
id: productOne.id,
|
product: {
|
||||||
|
id: productOne.id,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -196,18 +198,15 @@ describe("ProductModuleService product options", () => {
|
|||||||
expect(option).toEqual(
|
expect(option).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: optionOne.id,
|
id: optionOne.id,
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should return requested attributes when requested through config", async () => {
|
it("should return requested attributes when requested through config", async () => {
|
||||||
const option = await service.retrieveOption(
|
const option = await service.retrieveOption(optionOne.id, {
|
||||||
optionOne.id,
|
select: ["id", "product.title"],
|
||||||
{
|
relations: ["product"],
|
||||||
select: ["id", "product.title"],
|
})
|
||||||
relations: ["product"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(option).toEqual(
|
expect(option).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -216,7 +215,7 @@ describe("ProductModuleService product options", () => {
|
|||||||
id: "product-1",
|
id: "product-1",
|
||||||
title: "product 1",
|
title: "product 1",
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -229,7 +228,9 @@ describe("ProductModuleService product options", () => {
|
|||||||
error = e
|
error = e
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(error.message).toEqual("ProductOption with id: does-not-exist was not found")
|
expect(error.message).toEqual(
|
||||||
|
"ProductOption with id: does-not-exist was not found"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -237,12 +238,10 @@ describe("ProductModuleService product options", () => {
|
|||||||
const optionId = "option-1"
|
const optionId = "option-1"
|
||||||
|
|
||||||
it("should delete the product option given an ID successfully", async () => {
|
it("should delete the product option given an ID successfully", async () => {
|
||||||
await service.deleteOptions(
|
await service.deleteOptions([optionId])
|
||||||
[optionId],
|
|
||||||
)
|
|
||||||
|
|
||||||
const options = await service.listOptions({
|
const options = await service.listOptions({
|
||||||
id: optionId
|
id: optionId,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(options).toHaveLength(0)
|
expect(options).toHaveLength(0)
|
||||||
@@ -253,12 +252,12 @@ describe("ProductModuleService product options", () => {
|
|||||||
const optionId = "option-1"
|
const optionId = "option-1"
|
||||||
|
|
||||||
it("should update the title of the option successfully", async () => {
|
it("should update the title of the option successfully", async () => {
|
||||||
await service.updateOptions(
|
await service.updateOptions([
|
||||||
[{
|
{
|
||||||
id: optionId,
|
id: optionId,
|
||||||
title: "new test"
|
title: "new test",
|
||||||
}]
|
},
|
||||||
)
|
])
|
||||||
|
|
||||||
const productOption = await service.retrieveOption(optionId)
|
const productOption = await service.retrieveOption(optionId)
|
||||||
|
|
||||||
@@ -272,29 +271,45 @@ describe("ProductModuleService product options", () => {
|
|||||||
await service.updateOptions([
|
await service.updateOptions([
|
||||||
{
|
{
|
||||||
id: "does-not-exist",
|
id: "does-not-exist",
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e
|
error = e
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(error.message).toEqual('ProductOption with id "does-not-exist" not found')
|
expect(error.message).toEqual(
|
||||||
|
'ProductOption with id "does-not-exist" not found'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("createOptions", () => {
|
describe("createOptions", () => {
|
||||||
it("should create a option successfully", async () => {
|
it("should create a option successfully", async () => {
|
||||||
const res = await service.createOptions([{
|
const res = await service.createOptions([
|
||||||
title: "test",
|
{
|
||||||
product_id: productOne.id
|
title: "test",
|
||||||
}])
|
product_id: productOne.id,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
const productOption = await service.listOptions({
|
const [productOption] = await service.listOptions(
|
||||||
title: "test"
|
{
|
||||||
})
|
title: "test",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
select: ["id", "title", "product.id"],
|
||||||
|
relations: ["product"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
expect(productOption[0]?.title).toEqual("test")
|
expect(productOption).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
title: "test",
|
||||||
|
product: expect.objectContaining({
|
||||||
|
id: productOne.id,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { DAL } from "@medusajs/types"
|
||||||
import { DALUtils, generateEntityId } from "@medusajs/utils"
|
import { DALUtils, generateEntityId } from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
BeforeCreate,
|
BeforeCreate,
|
||||||
@@ -14,7 +15,6 @@ import {
|
|||||||
} from "@mikro-orm/core"
|
} from "@mikro-orm/core"
|
||||||
import { Product } from "./index"
|
import { Product } from "./index"
|
||||||
import ProductOptionValue from "./product-option-value"
|
import ProductOptionValue from "./product-option-value"
|
||||||
import { DAL } from "@medusajs/types"
|
|
||||||
|
|
||||||
type OptionalRelations =
|
type OptionalRelations =
|
||||||
| "values"
|
| "values"
|
||||||
@@ -39,8 +39,9 @@ class ProductOption {
|
|||||||
@ManyToOne(() => Product, {
|
@ManyToOne(() => Product, {
|
||||||
index: "IDX_product_option_product_id",
|
index: "IDX_product_option_product_id",
|
||||||
fieldName: "product_id",
|
fieldName: "product_id",
|
||||||
|
nullable: true,
|
||||||
})
|
})
|
||||||
product: Product
|
product!: Product
|
||||||
|
|
||||||
@OneToMany(() => ProductOptionValue, (value) => value.option, {
|
@OneToMany(() => ProductOptionValue, (value) => value.option, {
|
||||||
cascade: [Cascade.REMOVE, "soft-remove" as any],
|
cascade: [Cascade.REMOVE, "soft-remove" as any],
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
import { ProductCollection } from "@models"
|
import { Context, DAL, ProductTypes } from "@medusajs/types"
|
||||||
|
import { DALUtils, MedusaError } from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
|
LoadStrategy,
|
||||||
FilterQuery as MikroFilterQuery,
|
FilterQuery as MikroFilterQuery,
|
||||||
FindOptions as MikroOptions,
|
FindOptions as MikroOptions,
|
||||||
LoadStrategy,
|
|
||||||
} from "@mikro-orm/core"
|
} from "@mikro-orm/core"
|
||||||
import { Context, DAL, ProductTypes } from "@medusajs/types"
|
|
||||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
import { DALUtils, MedusaError } from "@medusajs/utils"
|
import { ProductCollection } from "@models"
|
||||||
|
|
||||||
|
type UpdateProductCollection = ProductTypes.UpdateProductCollectionDTO & {
|
||||||
|
products?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateProductCollection = ProductTypes.CreateProductCollectionDTO & {
|
||||||
|
products?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
export class ProductCollectionRepository extends DALUtils.MikroOrmBaseRepository {
|
export class ProductCollectionRepository extends DALUtils.MikroOrmBaseRepository {
|
||||||
@@ -71,12 +79,18 @@ export class ProductCollectionRepository extends DALUtils.MikroOrmBaseRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
async create(
|
async create(
|
||||||
data: ProductTypes.CreateProductCollectionDTO[],
|
data: CreateProductCollection[],
|
||||||
context: Context = {}
|
context: Context = {}
|
||||||
): Promise<ProductCollection[]> {
|
): Promise<ProductCollection[]> {
|
||||||
const manager = this.getActiveManager<SqlEntityManager>(context)
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
|
|
||||||
const productCollections = data.map((collectionData) => {
|
const productCollections = data.map((collectionData) => {
|
||||||
|
if (collectionData.product_ids) {
|
||||||
|
collectionData.products = collectionData.product_ids
|
||||||
|
|
||||||
|
delete collectionData.product_ids
|
||||||
|
}
|
||||||
|
|
||||||
return manager.create(ProductCollection, collectionData)
|
return manager.create(ProductCollection, collectionData)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -86,7 +100,7 @@ export class ProductCollectionRepository extends DALUtils.MikroOrmBaseRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
async update(
|
async update(
|
||||||
data: ProductTypes.UpdateProductCollectionDTO[],
|
data: UpdateProductCollection[],
|
||||||
context: Context = {}
|
context: Context = {}
|
||||||
): Promise<ProductCollection[]> {
|
): Promise<ProductCollection[]> {
|
||||||
const manager = this.getActiveManager<SqlEntityManager>(context)
|
const manager = this.getActiveManager<SqlEntityManager>(context)
|
||||||
@@ -119,6 +133,12 @@ export class ProductCollectionRepository extends DALUtils.MikroOrmBaseRepository
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (collectionData.product_ids) {
|
||||||
|
collectionData.products = collectionData.product_ids
|
||||||
|
|
||||||
|
delete collectionData.product_ids
|
||||||
|
}
|
||||||
|
|
||||||
return manager.assign(existingCollection, collectionData)
|
return manager.assign(existingCollection, collectionData)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
|
import { Context, DAL, ProductTypes } from "@medusajs/types"
|
||||||
|
import { DALUtils, MedusaError } from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
|
LoadStrategy,
|
||||||
FilterQuery as MikroFilterQuery,
|
FilterQuery as MikroFilterQuery,
|
||||||
FindOptions as MikroOptions,
|
FindOptions as MikroOptions,
|
||||||
LoadStrategy,
|
|
||||||
} from "@mikro-orm/core"
|
} from "@mikro-orm/core"
|
||||||
import { Product, ProductOption } from "@models"
|
|
||||||
import { Context, DAL, ProductTypes } from "@medusajs/types"
|
|
||||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
import { DALUtils, MedusaError } from "@medusajs/utils"
|
import { Product, ProductOption } from "@models"
|
||||||
|
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
export class ProductOptionRepository extends DALUtils.MikroOrmAbstractBaseRepository<ProductOption> {
|
export class ProductOptionRepository extends DALUtils.MikroOrmAbstractBaseRepository<ProductOption> {
|
||||||
@@ -97,7 +97,7 @@ export class ProductOptionRepository extends DALUtils.MikroOrmAbstractBaseReposi
|
|||||||
if (productId) {
|
if (productId) {
|
||||||
const product = existingProductsMap.get(productId)
|
const product = existingProductsMap.get(productId)
|
||||||
|
|
||||||
optionData.product = product
|
optionData.product_id = product?.id
|
||||||
}
|
}
|
||||||
|
|
||||||
return manager.create(ProductOption, optionData)
|
return manager.create(ProductOption, optionData)
|
||||||
|
|||||||
@@ -446,7 +446,11 @@ export default class ProductModuleService<
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
return JSON.parse(JSON.stringify(productOptions))
|
return await this.baseRepository_.serialize<
|
||||||
|
ProductTypes.ProductOptionDTO[]
|
||||||
|
>(productOptions, {
|
||||||
|
populate: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
||||||
@@ -459,7 +463,11 @@ export default class ProductModuleService<
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
return JSON.parse(JSON.stringify(productOptions))
|
return await this.baseRepository_.serialize<
|
||||||
|
ProductTypes.ProductOptionDTO[]
|
||||||
|
>(productOptions, {
|
||||||
|
populate: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export interface ProductDTO {
|
|||||||
is_giftcard: boolean
|
is_giftcard: boolean
|
||||||
status: ProductStatus
|
status: ProductStatus
|
||||||
thumbnail?: string | null
|
thumbnail?: string | null
|
||||||
|
width?: number | null
|
||||||
weight?: number | null
|
weight?: number | null
|
||||||
length?: number | null
|
length?: number | null
|
||||||
height?: number | null
|
height?: number | null
|
||||||
@@ -41,6 +42,7 @@ export interface ProductDTO {
|
|||||||
created_at?: string | Date
|
created_at?: string | Date
|
||||||
updated_at?: string | Date
|
updated_at?: string | Date
|
||||||
deleted_at?: string | Date
|
deleted_at?: string | Date
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProductVariantDTO {
|
export interface ProductVariantDTO {
|
||||||
@@ -193,6 +195,7 @@ export interface FilterableProductOptionProps
|
|||||||
export interface FilterableProductCollectionProps
|
export interface FilterableProductCollectionProps
|
||||||
extends BaseFilterable<FilterableProductCollectionProps> {
|
extends BaseFilterable<FilterableProductCollectionProps> {
|
||||||
id?: string | string[]
|
id?: string | string[]
|
||||||
|
handle?: string | string[]
|
||||||
title?: string
|
title?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +225,7 @@ export interface FilterableProductCategoryProps
|
|||||||
export interface CreateProductCollectionDTO {
|
export interface CreateProductCollectionDTO {
|
||||||
title: string
|
title: string
|
||||||
handle?: string
|
handle?: string
|
||||||
products?: ProductDTO[]
|
product_ids?: string[]
|
||||||
metadata?: Record<string, unknown>
|
metadata?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +234,7 @@ export interface UpdateProductCollectionDTO {
|
|||||||
value?: string
|
value?: string
|
||||||
title?: string
|
title?: string
|
||||||
handle?: string
|
handle?: string
|
||||||
products?: ProductDTO[]
|
product_ids?: string[]
|
||||||
metadata?: Record<string, unknown>
|
metadata?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +272,6 @@ export interface UpdateProductTagDTO {
|
|||||||
export interface CreateProductOptionDTO {
|
export interface CreateProductOptionDTO {
|
||||||
title: string
|
title: string
|
||||||
product_id?: string
|
product_id?: string
|
||||||
product?: Record<any, any>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateProductOptionDTO {
|
export interface UpdateProductOptionDTO {
|
||||||
|
|||||||
Reference in new issue
Block a user