chore: Hide repository creation if they are not custom + add upsert support by default (#6127)

This commit is contained in:
Adrien de Peretti authored and GitHub committed 2024-01-19 15:09:38 +01:00
1 parent 8a8a7183b8
commit 5e655dd59b
124 files changed
+1516 -2559

No files matched your search

@@ -1,12 +1,17 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { ProductCategory } from "@models"
import { ProductCategoryRepository } from "@repositories"
import { ProductCategoryService } from "@services"
import { createProductCategories } from "../../../__fixtures__/product-category"
import { productCategoriesData, productCategoriesRankData } from "../../../__fixtures__/product-category/data"
import {
productCategoriesData,
productCategoriesRankData,
} from "../../../__fixtures__/product-category/data"
import { TestDatabase } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -20,13 +25,12 @@ describe("Product category Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productCategoryRepository = new ProductCategoryRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductCategoryService<ProductCategory>({
productCategoryRepository,
})
await ContainerLoader({ container })
service = container.resolve("productCategoryService")
})
afterEach(async () => {
@@ -244,13 +248,11 @@ describe("Product category Service", () => {
})
it("should return category for the given id", async () => {
const productCategoryResults = await service.retrieve(
categoryOneId,
)
const productCategoryResults = await service.retrieve(categoryOneId)
expect(productCategoryResults).toEqual(
expect.objectContaining({
id: categoryOneId
id: categoryOneId,
})
)
})
@@ -264,7 +266,9 @@ describe("Product category Service", () => {
error = e
}
expect(error.message).toEqual('ProductCategory with id: does-not-exist was not found')
expect(error.message).toEqual(
"ProductCategory with id: does-not-exist was not found"
)
})
it("should throw an error when an id is not provided", async () => {
@@ -280,44 +284,38 @@ describe("Product category Service", () => {
})
it("should return category based on config select param", async () => {
const productCategoryResults = await service.retrieve(
categoryOneId,
{
select: ["id", "parent_category_id"],
}
)
const productCategoryResults = await service.retrieve(categoryOneId, {
select: ["id", "parent_category_id"],
})
expect(productCategoryResults).toEqual(
expect.objectContaining({
id: categoryOneId,
id: categoryOneId,
parent_category_id: "category-0",
})
)
})
it("should return category based on config relation param", async () => {
const productCategoryResults = await service.retrieve(
categoryOneId,
{
select: ["id", "parent_category_id"],
relations: ["parent_category"]
}
)
const productCategoryResults = await service.retrieve(categoryOneId, {
select: ["id", "parent_category_id"],
relations: ["parent_category"],
})
expect(productCategoryResults).toEqual(
expect.objectContaining({
id: categoryOneId,
id: categoryOneId,
category_children: [
expect.objectContaining({
id: 'category-1-a',
id: "category-1-a",
}),
expect.objectContaining({
id: 'category-1-b',
})
id: "category-1-b",
}),
],
parent_category: expect.objectContaining({
id: "category-0"
})
id: "category-0",
}),
})
)
})
@@ -352,7 +350,7 @@ describe("Product category Service", () => {
{},
{
take: 1,
skip: 1
skip: 1,
}
)
@@ -377,7 +375,7 @@ describe("Product category Service", () => {
expect(productCategoryResults[0]).toEqual([
expect.objectContaining({
id: "category-0",
parent_category: null
parent_category: null,
}),
expect.objectContaining({
id: "category-1",
@@ -568,11 +566,14 @@ describe("Product category Service", () => {
parent_category_id: null,
})
const [productCategory] = await service.list({
name: "New Category"
}, {
select: ["name", "rank"]
})
const [productCategory] = await service.list(
{
name: "New Category",
},
{
select: ["name", "rank"],
}
)
expect(productCategory).toEqual(
expect.objectContaining({
@@ -586,7 +587,7 @@ describe("Product category Service", () => {
await service.create({
name: "New Category",
parent_category_id: null,
rank: 0
rank: 0,
})
await service.create({
@@ -594,11 +595,14 @@ describe("Product category Service", () => {
parent_category_id: null,
})
const [productCategoryNew] = await service.list({
name: "New Category 2"
}, {
select: ["name", "rank"]
})
const [productCategoryNew] = await service.list(
{
name: "New Category 2",
},
{
select: ["name", "rank"],
}
)
expect(productCategoryNew).toEqual(
expect.objectContaining({
@@ -612,11 +616,14 @@ describe("Product category Service", () => {
parent_category_id: productCategoryNew.id,
})
const [productCategoryWithParent] = await service.list({
name: "New Category 2.1"
}, {
select: ["name", "rank", "parent_category_id"]
})
const [productCategoryWithParent] = await service.list(
{
name: "New Category 2.1",
},
{
select: ["name", "rank", "parent_category_id"],
}
)
expect(productCategoryWithParent).toEqual(
expect.objectContaining({
@@ -655,11 +662,11 @@ describe("Product category Service", () => {
it("should update the name of the category successfully", async () => {
await service.update(productCategoryZero.id, {
name: "New Category"
name: "New Category",
})
const productCategory = await service.retrieve(productCategoryZero.id, {
select: ["name"]
select: ["name"],
})
expect(productCategory.name).toEqual("New Category")
@@ -670,13 +677,15 @@ describe("Product category Service", () => {
try {
await service.update("does-not-exist", {
name: "New Category"
name: "New Category",
})
} catch (e) {
error = e
}
expect(error.message).toEqual(`ProductCategory not found ({ id: 'does-not-exist' })`)
expect(error.message).toEqual(
`ProductCategory not found ({ id: 'does-not-exist' })`
)
})
it("should reorder rank successfully in the same parent", async () => {
@@ -684,11 +693,14 @@ describe("Product category Service", () => {
rank: 0,
})
const productCategories = await service.list({
parent_category_id: null
}, {
select: ["name", "rank"]
})
const productCategories = await service.list(
{
parent_category_id: null,
},
{
select: ["name", "rank"],
}
)
expect(productCategories).toEqual(
expect.arrayContaining([
@@ -703,7 +715,7 @@ describe("Product category Service", () => {
expect.objectContaining({
id: productCategoryOne.id,
rank: "2",
})
}),
])
)
})
@@ -711,14 +723,17 @@ describe("Product category Service", () => {
it("should reorder rank successfully when changing parent", async () => {
await service.update(productCategoryTwo.id, {
rank: 0,
parent_category_id: productCategoryZero.id
parent_category_id: productCategoryZero.id,
})
const productCategories = await service.list({
parent_category_id: productCategoryZero.id
}, {
select: ["name", "rank"]
})
const productCategories = await service.list(
{
parent_category_id: productCategoryZero.id,
},
{
select: ["name", "rank"],
}
)
expect(productCategories).toEqual(
expect.arrayContaining([
@@ -737,7 +752,7 @@ describe("Product category Service", () => {
expect.objectContaining({
id: productCategoryZeroTwo.id,
rank: "3",
})
}),
])
)
})
@@ -745,14 +760,17 @@ describe("Product category Service", () => {
it("should reorder rank successfully when changing parent and in first position", async () => {
await service.update(productCategoryTwo.id, {
rank: 0,
parent_category_id: productCategoryZero.id
parent_category_id: productCategoryZero.id,
})
const productCategories = await service.list({
parent_category_id: productCategoryZero.id
}, {
select: ["name", "rank"]
})
const productCategories = await service.list(
{
parent_category_id: productCategoryZero.id,
},
{
select: ["name", "rank"],
}
)
expect(productCategories).toEqual(
expect.arrayContaining([
@@ -771,7 +789,7 @@ describe("Product category Service", () => {
expect.objectContaining({
id: productCategoryZeroTwo.id,
rank: "3",
})
}),
])
)
})
@@ -805,7 +823,9 @@ describe("Product category Service", () => {
error = e
}
expect(error.message).toEqual(`ProductCategory not found ({ id: 'does-not-exist' })`)
expect(error.message).toEqual(
`ProductCategory not found ({ id: 'does-not-exist' })`
)
})
it("should throw an error when it has children", async () => {
@@ -817,17 +837,22 @@ describe("Product category Service", () => {
error = e
}
expect(error.message).toEqual(`Deleting ProductCategory (category-0-0) with category children is not allowed`)
expect(error.message).toEqual(
`Deleting ProductCategory (category-0-0) with category children is not allowed`
)
})
it("should reorder siblings rank successfully on deleting", async () => {
await service.delete(productCategoryOne.id)
const productCategories = await service.list({
parent_category_id: null
}, {
select: ["id", "rank"]
})
const productCategories = await service.list(
{
parent_category_id: null,
},
{
select: ["id", "rank"],
}
)
expect(productCategories).toEqual(
expect.arrayContaining([
@@ -838,7 +863,7 @@ describe("Product category Service", () => {
expect.objectContaining({
id: productCategoryTwo.id,
rank: "1",
})
}),
])
)
})
@@ -1,11 +1,13 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { ProductCollection } from "@models"
import { ProductCollectionRepository } from "@repositories"
import { ProductCollectionService } from "@services"
import { createCollections } from "../../../__fixtures__/product"
import { TestDatabase } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -19,13 +21,12 @@ describe("Product collection Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productCollectionRepository = new ProductCollectionRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductCollectionService({
productCollectionRepository,
})
await ContainerLoader({ container })
service = container.resolve("productCollectionService")
})
afterEach(async () => {
@@ -93,7 +94,9 @@ describe("Product collection Service", () => {
})
it("list product collections by title matching string", async () => {
const productCollectionResults = await service.list({ title: "col 3 extra" })
const productCollectionResults = await service.list({
title: "col 3 extra",
})
expect(productCollectionResults).toEqual([
expect.objectContaining({
@@ -155,7 +158,9 @@ describe("Product collection Service", () => {
})
it("should return count and collections based on filter data", async () => {
const [productCollectionResults, count] = await service.listAndCount({ id: data![0].id })
const [productCollectionResults, count] = await service.listAndCount({
id: data![0].id,
})
const serialized = JSON.parse(JSON.stringify(productCollectionResults))
expect(count).toEqual(1)
@@ -168,12 +173,15 @@ describe("Product collection Service", () => {
})
it("should return count and collections based on config data", async () => {
const [productCollectionResults, count] = await service.listAndCount({}, {
relations: ['products'],
select: ['title'],
take: 1,
skip: 1,
})
const [productCollectionResults, count] = await service.listAndCount(
{},
{
relations: ["products"],
select: ["title"],
take: 1,
skip: 1,
}
)
const serialized = JSON.parse(JSON.stringify(productCollectionResults))
expect(count).toEqual(4)
@@ -181,7 +189,7 @@ describe("Product collection Service", () => {
{
id: "test-2",
title: "col 2",
products: []
products: [],
},
])
})
@@ -200,13 +208,11 @@ describe("Product collection Service", () => {
})
it("should return collection for the given id", async () => {
const productCollectionResults = await service.retrieve(
collectionData.id,
)
const productCollectionResults = await service.retrieve(collectionData.id)
expect(productCollectionResults).toEqual(
expect.objectContaining({
id: collectionData.id
id: collectionData.id,
})
)
})
@@ -220,7 +226,9 @@ describe("Product collection Service", () => {
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"
)
})
it("should throw an error when an id is not provided", async () => {
@@ -245,12 +253,10 @@ describe("Product collection Service", () => {
const serialized = JSON.parse(JSON.stringify(productCollectionResults))
expect(serialized).toEqual(
{
id: collectionData.id,
title: collectionData.title,
}
)
expect(serialized).toEqual({
id: collectionData.id,
title: collectionData.title,
})
})
it("should return collection based on config relation param", async () => {
@@ -258,19 +264,17 @@ describe("Product collection Service", () => {
collectionData.id,
{
select: ["id", "title"],
relations: ["products"]
relations: ["products"],
}
)
const serialized = JSON.parse(JSON.stringify(productCollectionResults))
expect(serialized).toEqual(
{
id: collectionData.id,
title: collectionData.title,
products: []
}
)
expect(serialized).toEqual({
id: collectionData.id,
title: collectionData.title,
products: [],
})
})
})
@@ -288,12 +292,10 @@ describe("Product collection Service", () => {
})
it("should delete the product collection given an ID successfully", async () => {
await service.delete(
[collectionId],
)
await service.delete([collectionId])
const collections = await service.list({
id: collectionId
id: collectionId,
})
expect(collections).toHaveLength(0)
@@ -314,12 +316,12 @@ describe("Product collection Service", () => {
})
it("should update the value of the collection successfully", async () => {
await service.update(
[{
await service.update([
{
id: collectionId,
title: "New Collection"
}]
)
title: "New Collection",
},
])
const productCollection = await service.retrieve(collectionId)
@@ -331,29 +333,31 @@ describe("Product collection Service", () => {
try {
await service.update([
{
id: "does-not-exist",
title: "New Collection"
}
])
{
id: "does-not-exist",
title: "New Collection",
},
])
} catch (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("create", () => {
it("should create a collection successfully", async () => {
await service.create(
[{
title: "New Collection"
}]
)
await service.create([
{
title: "New Collection",
},
])
const [productCollection] = await service.list({
title: "New Collection"
title: "New Collection",
})
expect(productCollection.title).toEqual("New Collection")
@@ -1,12 +1,14 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { ProductOptionService } from "@services"
import { ProductOptionRepository } from "@repositories"
import { Product } from "@models"
import { TestDatabase } from "../../../utils"
import { createOptions } from "../../../__fixtures__/product"
import { ProductTypes } from "@medusajs/types"
import { asValue } from "awilix"
import { createMedusaContainer } from "@medusajs/utils"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -34,13 +36,12 @@ describe("ProductOption Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productOptionRepository = new ProductOptionRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductOptionService({
productOptionRepository,
})
await ContainerLoader({ container })
service = container.resolve("productOptionService")
testManager = await TestDatabase.forkManager()
productOne = testManager.create(Product, productOneData)
@@ -1,12 +1,14 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Product } from "@models"
import { ProductTagRepository } from "@repositories"
import { ProductTagService } from "@services"
import { ProductTypes } from "@medusajs/types"
import { createProductAndTags } from "../../../__fixtures__/product"
import { TestDatabase } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -53,13 +55,12 @@ describe("ProductTag Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productTagRepository = new ProductTagRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductTagService({
productTagRepository,
})
await ContainerLoader({ container })
service = container.resolve("productTagService")
testManager = await TestDatabase.forkManager()
@@ -143,7 +144,9 @@ describe("ProductTag Service", () => {
})
it("should return product tags and count when filtered", async () => {
const [tagsResults, count] = await service.listAndCount({ id: data[0].tags![0].id })
const [tagsResults, count] = await service.listAndCount({
id: data[0].tags![0].id,
})
expect(count).toEqual(1)
expect(tagsResults).toEqual([
@@ -154,7 +157,10 @@ describe("ProductTag Service", () => {
})
it("should return product tags and count when using skip and take", async () => {
const [tagsResults, count] = await service.listAndCount({}, { skip: 1, take: 2 })
const [tagsResults, count] = await service.listAndCount(
{},
{ skip: 1, take: 2 }
)
expect(count).toEqual(4)
expect(tagsResults).toEqual([
@@ -168,11 +174,14 @@ describe("ProductTag Service", () => {
})
it("should return requested fields and relations", async () => {
const [tagsResults, count] = await service.listAndCount({}, {
take: 1,
select: ["value", "products.id"],
relations: ["products"]
})
const [tagsResults, count] = await service.listAndCount(
{},
{
take: 1,
select: ["value", "products.id"],
relations: ["products"],
}
)
const serialized = JSON.parse(JSON.stringify(tagsResults))
@@ -180,9 +189,11 @@ describe("ProductTag Service", () => {
expect(serialized).toEqual([
expect.objectContaining({
id: "tag-1",
products: [{
id: "test-1"
}]
products: [
{
id: "test-1",
},
],
}),
])
})
@@ -194,13 +205,11 @@ describe("ProductTag Service", () => {
const productId = "test-1"
it("should return tag for the given id", async () => {
const tag = await service.retrieve(
tagId,
)
const tag = await service.retrieve(tagId)
expect(tag).toEqual(
expect.objectContaining({
id: tagId
id: tagId,
})
)
})
@@ -214,7 +223,9 @@ describe("ProductTag Service", () => {
error = e
}
expect(error.message).toEqual('ProductTag with id: does-not-exist was not found')
expect(error.message).toEqual(
"ProductTag with id: does-not-exist was not found"
)
})
it("should throw an error when an id is not provided", async () => {
@@ -230,43 +241,35 @@ describe("ProductTag Service", () => {
})
it("should return tag based on config select param", async () => {
const tag = await service.retrieve(
tagId,
{
select: ["id", "value"],
}
)
const tag = await service.retrieve(tagId, {
select: ["id", "value"],
})
const serialized = JSON.parse(JSON.stringify(tag))
expect(serialized).toEqual(
{
id: tagId,
value: tagValue,
}
)
expect(serialized).toEqual({
id: tagId,
value: tagValue,
})
})
it("should return tag based on config relation param", async () => {
const tag = await service.retrieve(
tagId,
{
select: ["id", "value", "products.id"],
relations: ["products"]
}
)
const tag = await service.retrieve(tagId, {
select: ["id", "value", "products.id"],
relations: ["products"],
})
const serialized = JSON.parse(JSON.stringify(tag))
expect(serialized).toEqual(
{
id: tagId,
value: tagValue,
products: [{
id: productId
}]
}
)
expect(serialized).toEqual({
id: tagId,
value: tagValue,
products: [
{
id: productId,
},
],
})
})
})
@@ -274,12 +277,10 @@ describe("ProductTag Service", () => {
const tagId = "tag-1"
it("should delete the product tag given an ID successfully", async () => {
await service.delete(
[tagId],
)
await service.delete([tagId])
const tags = await service.list({
id: tagId
id: tagId,
})
expect(tags).toHaveLength(0)
@@ -290,12 +291,12 @@ describe("ProductTag Service", () => {
const tagId = "tag-1"
it("should update the value of the tag successfully", async () => {
await service.update(
[{
await service.update([
{
id: tagId,
value: "UK"
}]
)
value: "UK",
},
])
const productTag = await service.retrieve(tagId)
@@ -307,29 +308,31 @@ describe("ProductTag Service", () => {
try {
await service.update([
{
id: "does-not-exist",
value: "UK"
}
])
{
id: "does-not-exist",
value: "UK",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual('ProductTag with id "does-not-exist" not found')
expect(error.message).toEqual(
'ProductTag with id "does-not-exist" not found'
)
})
})
describe("create", () => {
it("should create a tag successfully", async () => {
await service.create(
[{
value: "UK"
}]
)
await service.create([
{
value: "UK",
},
])
const [productTag] = await service.list({
value: "UK"
value: "UK",
})
expect(productTag.value).toEqual("UK")
@@ -1,12 +1,14 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import ContainerLoader from "../../../../src/loaders/container"
import { ProductTypeService } from "@services"
import { ProductTypeRepository } from "@repositories"
import { Product } from "@models"
import { TestDatabase } from "../../../utils"
import { createProductAndTypes } from "../../../__fixtures__/product"
import { ProductTypes } from "@medusajs/types"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
jest.setTimeout(30000)
@@ -33,7 +35,7 @@ describe("ProductType Service", () => {
type: {
id: "type-2",
value: "Type 2",
}
},
},
]
@@ -41,13 +43,12 @@ describe("ProductType Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productTypeRepository = new ProductTypeRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductTypeService({
productTypeRepository,
})
await ContainerLoader({ container })
service = container.resolve("productTypeService")
testManager = await TestDatabase.forkManager()
@@ -115,7 +116,9 @@ describe("ProductType Service", () => {
})
it("should return product type and count when filtered", async () => {
const [typeResults, count] = await service.listAndCount({ id: data[0].type.id })
const [typeResults, count] = await service.listAndCount({
id: data[0].type.id,
})
expect(count).toEqual(1)
expect(typeResults).toEqual([
@@ -126,7 +129,10 @@ describe("ProductType Service", () => {
})
it("should return product type and count when using skip and take", async () => {
const [typeResults, count] = await service.listAndCount({}, { skip: 1, take: 1 })
const [typeResults, count] = await service.listAndCount(
{},
{ skip: 1, take: 1 }
)
expect(count).toEqual(2)
expect(typeResults).toEqual([
@@ -137,10 +143,13 @@ describe("ProductType Service", () => {
})
it("should return requested fields", async () => {
const [typeResults, count] = await service.listAndCount({}, {
take: 1,
select: ["value"],
})
const [typeResults, count] = await service.listAndCount(
{},
{
take: 1,
select: ["value"],
}
)
const serialized = JSON.parse(JSON.stringify(typeResults))
@@ -158,13 +167,11 @@ describe("ProductType Service", () => {
const typeValue = "Type 1"
it("should return type for the given id", async () => {
const type = await service.retrieve(
typeId,
)
const type = await service.retrieve(typeId)
expect(type).toEqual(
expect.objectContaining({
id: typeId
id: typeId,
})
)
})
@@ -178,7 +185,9 @@ describe("ProductType Service", () => {
error = e
}
expect(error.message).toEqual('ProductType with id: does-not-exist was not found')
expect(error.message).toEqual(
"ProductType with id: does-not-exist was not found"
)
})
it("should throw an error when an id is not provided", async () => {
@@ -194,21 +203,16 @@ describe("ProductType Service", () => {
})
it("should return type based on config select param", async () => {
const type = await service.retrieve(
typeId,
{
select: ["id", "value"],
}
)
const type = await service.retrieve(typeId, {
select: ["id", "value"],
})
const serialized = JSON.parse(JSON.stringify(type))
expect(serialized).toEqual(
{
id: typeId,
value: typeValue,
}
)
expect(serialized).toEqual({
id: typeId,
value: typeValue,
})
})
})
@@ -216,12 +220,10 @@ describe("ProductType Service", () => {
const typeId = "type-1"
it("should delete the product type given an ID successfully", async () => {
await service.delete(
[typeId],
)
await service.delete([typeId])
const types = await service.list({
id: typeId
id: typeId,
})
expect(types).toHaveLength(0)
@@ -232,12 +234,12 @@ describe("ProductType Service", () => {
const typeId = "type-1"
it("should update the value of the type successfully", async () => {
await service.update(
[{
await service.update([
{
id: typeId,
value: "UK"
}]
)
value: "UK",
},
])
const productType = await service.retrieve(typeId)
@@ -249,29 +251,31 @@ describe("ProductType Service", () => {
try {
await service.update([
{
id: "does-not-exist",
value: "UK"
}
])
{
id: "does-not-exist",
value: "UK",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual('ProductType with id "does-not-exist" not found')
expect(error.message).toEqual(
'ProductType with id "does-not-exist" not found'
)
})
})
describe("create", () => {
it("should create a type successfully", async () => {
await service.create(
[{
value: "UK"
}]
)
await service.create([
{
value: "UK",
},
])
const [productType] = await service.list({
value: "UK"
value: "UK",
})
expect(productType.value).toEqual("UK")
@@ -1,6 +1,5 @@
import { TestDatabase } from "../../../utils"
import { ProductService, ProductVariantService } from "@services"
import { ProductRepository, ProductVariantRepository } from "@repositories"
import { ProductVariantService } from "@services"
import { Product, ProductTag, ProductVariant } from "@models"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Collection } from "@mikro-orm/core"
@@ -13,6 +12,9 @@ import {
} from "../../../__fixtures__/product"
import { productsData, variantsData } from "../../../__fixtures__/product/data"
import { buildProductVariantOnlyData } from "../../../__fixtures__/variant/data/create-variant"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
describe("ProductVariant Service", () => {
let service: ProductVariantService
@@ -27,20 +29,12 @@ describe("ProductVariant Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productVariantRepository = new ProductVariantRepository({
manager: repositoryManager,
})
const productRepository = new ProductRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
const productService = new ProductService({
productRepository,
})
service = new ProductVariantService({
productService,
productVariantRepository,
})
await ContainerLoader({ container })
service = container.resolve("productVariantService")
})
afterEach(async () => {
@@ -21,12 +21,13 @@ import {
} from "../../../__fixtures__/product/data"
import { ProductDTO, ProductTypes } from "@medusajs/types"
import { kebabCase } from "@medusajs/utils"
import { createMedusaContainer, kebabCase } from "@medusajs/utils"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { ProductRepository } from "@repositories"
import { ProductService } from "@services"
import { createProductCategories } from "../../../__fixtures__/product-category"
import { TestDatabase } from "../../../utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -44,13 +45,12 @@ describe("Product Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productRepository = new ProductRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductService({
productRepository,
})
await ContainerLoader({ container })
service = container.resolve("productService")
})
afterEach(async () => {
+9 -107
View File
@@ -1,108 +1,10 @@
import * as DefaultRepositories from "@repositories"
import {
BaseRepository,
ProductCategoryRepository,
ProductCollectionRepository,
ProductImageRepository,
ProductOptionRepository,
ProductOptionValueRepository,
ProductRepository,
ProductTagRepository,
ProductTypeRepository,
ProductVariantRepository,
} from "@repositories"
import { Constructor, DAL, ModulesSdkTypes } from "@medusajs/types"
import {
ProductCategoryService,
ProductCollectionService,
ProductImageService,
ProductModuleService,
ProductOptionService,
ProductOptionValueService,
ProductService,
ProductTagService,
ProductTypeService,
ProductVariantService,
} from "@services"
import { ModulesSdkUtils } from "@medusajs/utils"
import * as ModuleModels from "@models"
import * as ModuleRepositories from "@repositories"
import * as ModuleServices from "@services"
import { LoaderOptions } from "@medusajs/modules-sdk"
import { asClass } from "awilix"
import { lowerCaseFirst } from "@medusajs/utils"
export default async ({
container,
options,
}: LoaderOptions<
| ModulesSdkTypes.ModuleServiceInitializeOptions
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
>): Promise<void> => {
const customRepositories = (
options as ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
)?.repositories
container.register({
productModuleService: asClass(ProductModuleService).singleton(),
productService: asClass(ProductService).singleton(),
productCategoryService: asClass(ProductCategoryService).singleton(),
productVariantService: asClass(ProductVariantService).singleton(),
productTagService: asClass(ProductTagService).singleton(),
productCollectionService: asClass(ProductCollectionService).singleton(),
productImageService: asClass(ProductImageService).singleton(),
productTypeService: asClass(ProductTypeService).singleton(),
productOptionService: asClass(ProductOptionService).singleton(),
productOptionValueService: asClass(ProductOptionValueService).singleton(),
})
if (customRepositories) {
loadCustomRepositories({ customRepositories, container })
} else {
loadDefaultRepositories({ container })
}
}
function loadDefaultRepositories({ container }) {
container.register({
baseRepository: asClass(BaseRepository).singleton(),
productImageRepository: asClass(ProductImageRepository).singleton(),
productCategoryRepository: asClass(ProductCategoryRepository).singleton(),
productCollectionRepository: asClass(
ProductCollectionRepository
).singleton(),
productRepository: asClass(ProductRepository).singleton(),
productTagRepository: asClass(ProductTagRepository).singleton(),
productTypeRepository: asClass(ProductTypeRepository).singleton(),
productOptionRepository: asClass(ProductOptionRepository).singleton(),
productOptionValueRepository: asClass(
ProductOptionValueRepository
).singleton(),
productVariantRepository: asClass(ProductVariantRepository).singleton(),
})
}
/**
* Load the repositories from the custom repositories object. If a repository is not
* present in the custom repositories object, the default repository will be used.
*
* @param customRepositories
* @param container
*/
function loadCustomRepositories({ customRepositories, container }) {
const customRepositoriesMap = new Map(Object.entries(customRepositories))
Object.entries(DefaultRepositories).forEach(([key, DefaultRepository]) => {
let finalRepository = customRepositoriesMap.get(key)
if (
!finalRepository ||
!(finalRepository as Constructor<DAL.RepositoryService>).prototype.find
) {
finalRepository = DefaultRepository
}
container.register({
[lowerCaseFirst(key)]: asClass(
finalRepository as Constructor<DAL.RepositoryService>
).singleton(),
})
})
}
export default ModulesSdkUtils.moduleContainerLoaderFactory({
moduleModels: ModuleModels,
moduleRepositories: ModuleRepositories,
moduleServices: ModuleServices,
})
@@ -1,10 +1,4 @@
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
export { ProductRepository } from "./product"
export { ProductTagRepository } from "./product-tag"
export { ProductVariantRepository } from "./product-variant"
export { ProductCollectionRepository } from "./product-collection"
export { ProductCategoryRepository } from "./product-category"
export { ProductImageRepository } from "./product-image"
export { ProductTypeRepository } from "./product-type"
export { ProductOptionRepository } from "./product-option"
export { ProductOptionValueRepository } from "./product-option-value"
@@ -1,55 +0,0 @@
import { Context, ProductTypes } from "@medusajs/types"
import { DALUtils } 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
export class ProductCollectionRepository extends DALUtils.mikroOrmBaseRepositoryFactory(
ProductCollection
) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async create(
data: CreateProductCollection[],
context: Context = {}
): Promise<ProductCollection[]> {
const productCollections = data.map((collectionData) => {
if (collectionData.product_ids) {
collectionData.products = collectionData.product_ids
delete collectionData.product_ids
}
return collectionData
})
return await super.create(productCollections, context)
}
async update(
data: UpdateProductCollection[],
context: Context = {}
): Promise<ProductCollection[]> {
const productCollections = data.map((collectionData) => {
if (collectionData.product_ids) {
collectionData.products = collectionData.product_ids
delete collectionData.product_ids
}
return collectionData
})
return await super.update(productCollections, context)
}
}
@@ -1,7 +1,6 @@
import { Context } from "@medusajs/types"
import { Image } from "@models"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { DALUtils } from "@medusajs/utils"
import { Context } from "@medusajs/types"
// eslint-disable-next-line max-len
export class ProductImageRepository extends DALUtils.mikroOrmBaseRepositoryFactory(
@@ -13,41 +12,8 @@ export class ProductImageRepository extends DALUtils.mikroOrmBaseRepositoryFacto
}
async upsert(urls: string[], context: Context = {}): Promise<Image[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const data = urls.map((url) => ({ url }))
const existingImages = await this.find(
{
where: {
url: {
$in: urls,
},
},
},
context
)
const existingImagesMap = new Map<string, Image>(
existingImages.map<[string, Image]>((img) => [img.url, img])
)
const upsertedImgs: Image[] = []
const imageToCreate: Image[] = []
urls.forEach((url) => {
const aImg = existingImagesMap.get(url)
if (aImg) {
upsertedImgs.push(aImg)
} else {
const newImg = (manager as SqlEntityManager).create(Image, { url })
imageToCreate.push(newImg)
}
})
if (imageToCreate.length) {
manager.persist(imageToCreate)
upsertedImgs.push(...imageToCreate)
}
return upsertedImgs
return await super.upsert(data, context)
}
}
@@ -1,89 +0,0 @@
import { Context } from "@medusajs/types"
import {
CreateProductOptionValueDTO,
UpdateProductOptionValueDTO,
} from "../types/services/product-option-value"
import { DALUtils } from "@medusajs/utils"
import { ProductOptionValue } from "@models"
import { SqlEntityManager } from "@mikro-orm/postgresql"
export class ProductOptionValueRepository extends DALUtils.mikroOrmBaseRepositoryFactory(
ProductOptionValue
) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async upsert(
optionValues: (UpdateProductOptionValueDTO | CreateProductOptionValueDTO)[],
context: Context = {}
): Promise<ProductOptionValue[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const optionValueIds: string[] = []
for (const optionValue of optionValues) {
if (optionValue.id) {
optionValueIds.push(optionValue.id)
}
}
const existingOptionValues = await this.find(
{
where: {
id: {
$in: optionValueIds,
},
},
},
context
)
const existingOptionValuesMap = new Map(
existingOptionValues.map<[string, ProductOptionValue]>((optionValue) => [
optionValue.id,
optionValue,
])
)
const upsertedOptionValues: ProductOptionValue[] = []
const optionValuesToCreate: ProductOptionValue[] = []
const optionValuesToUpdate: ProductOptionValue[] = []
optionValues.forEach(({ option_id, ...optionValue }) => {
const existingOptionValue = optionValue.id
? existingOptionValuesMap.get(optionValue.id)
: undefined
if (optionValue.id && existingOptionValue) {
const updatedOptionValue = manager.assign(existingOptionValue, {
option: option_id,
...optionValue,
})
optionValuesToUpdate.push(updatedOptionValue)
return
}
const newOptionValue = manager.create(ProductOptionValue, {
option: option_id,
variant: (optionValue as CreateProductOptionValueDTO).variant_id,
...optionValue,
})
optionValuesToCreate.push(newOptionValue)
})
if (optionValuesToCreate.length) {
manager.persist(optionValuesToCreate)
upsertedOptionValues.push(...optionValuesToCreate)
}
if (optionValuesToUpdate.length) {
manager.persist(optionValuesToUpdate)
upsertedOptionValues.push(...optionValuesToUpdate)
}
return upsertedOptionValues
}
}
@@ -1,112 +0,0 @@
import { Context, ProductTypes } from "@medusajs/types"
import { DALUtils } from "@medusajs/utils"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Product, ProductOption } from "@models"
// eslint-disable-next-line max-len
export class ProductOptionRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
ProductOption,
{
update: ProductTypes.UpdateProductOptionDTO
}
>(ProductOption) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async create(
data: ProductTypes.CreateProductOptionDTO[],
context: Context = {}
): Promise<ProductOption[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const productIds: string[] = []
data.forEach((d) => d.product_id && productIds.push(d.product_id))
const existingProducts = await manager.find(Product, {
id: { $in: productIds },
})
const existingProductsMap = new Map<string, Product>(
existingProducts.map<[string, Product]>((product) => [
product.id,
product,
])
)
const productOptions = data.map((optionData) => {
const productId = optionData.product_id
delete optionData.product_id
if (productId) {
const product = existingProductsMap.get(productId)
optionData.product_id = product?.id
}
return optionData
})
return await super.create(productOptions, context)
}
async upsert(
data:
| ProductTypes.CreateProductOptionDTO[]
| ProductTypes.UpdateProductOptionDTO[],
context: Context = {}
): Promise<ProductOption[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const optionIds = data.map((optionData) => optionData.id).filter((o) => o)
let existingOptions
let existingOptionsMap = new Map()
if (optionIds.length) {
existingOptions = await this.find(
{
where: {
id: {
$in: optionIds,
},
},
},
context
)
existingOptionsMap = new Map(
existingOptions.map((option) => [option.id, option])
)
}
const upsertedOptions: ProductOption[] = []
const optionsToCreate: ProductOption[] = []
const optionsToUpdate: ProductOption[] = []
data.forEach((option) => {
const existingOption = existingOptionsMap.get(option.id)
if (existingOption) {
const updatedOption = manager.assign(existingOption, option)
optionsToUpdate.push(updatedOption)
} else {
const newOption = manager.create(ProductOption, option)
optionsToCreate.push(newOption)
}
})
if (optionsToCreate.length) {
manager.persist(optionsToCreate)
upsertedOptions.push(...optionsToCreate)
}
if (optionsToUpdate.length) {
manager.persist(optionsToUpdate)
upsertedOptions.push(...optionsToUpdate)
}
return upsertedOptions
}
}
@@ -1,71 +0,0 @@
import { ProductTag } from "@models"
import {
Context,
CreateProductTagDTO,
UpdateProductTagDTO,
UpsertProductTagDTO,
} from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { DALUtils } from "@medusajs/utils"
export class ProductTagRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
ProductTag,
{
create: CreateProductTagDTO
update: UpdateProductTagDTO
}
>(ProductTag) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async upsert(
tags: UpsertProductTagDTO[],
context: Context = {}
): Promise<ProductTag[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const tagsValues = tags.map((tag) => tag.value)
const existingTags = await this.find(
{
where: {
value: {
$in: tagsValues,
},
},
},
context
)
const existingTagsMap = new Map(
existingTags.map<[string, ProductTag]>((tag) => [tag.value, tag])
)
const upsertedTags: ProductTag[] = []
const tagsToCreate: ProductTag[] = []
const tagsToUpdate: ProductTag[] = []
tags.forEach((tag) => {
const aTag = existingTagsMap.get(tag.value)
if (aTag) {
const updatedTag = manager.assign(aTag, tag)
tagsToUpdate.push(updatedTag)
} else {
const newTag = manager.create(ProductTag, tag)
tagsToCreate.push(newTag)
}
})
if (tagsToCreate.length) {
manager.persist(tagsToCreate)
upsertedTags.push(...tagsToCreate)
}
if (tagsToUpdate.length) {
manager.persist(tagsToUpdate)
upsertedTags.push(...tagsToUpdate)
}
return upsertedTags
}
}
@@ -1,71 +0,0 @@
import { ProductType } from "@models"
import {
Context,
CreateProductTypeDTO,
UpdateProductTypeDTO,
} from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { DALUtils } from "@medusajs/utils"
export class ProductTypeRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
ProductType,
{
create: CreateProductTypeDTO
update: UpdateProductTypeDTO
}
>(ProductType) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async upsert(
types: CreateProductTypeDTO[],
context: Context = {}
): Promise<ProductType[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const typesValues = types.map((type) => type.value)
const existingTypes = await this.find(
{
where: {
value: {
$in: typesValues,
},
},
},
context
)
const existingTypesMap = new Map(
existingTypes.map<[string, ProductType]>((type) => [type.value, type])
)
const upsertedTypes: ProductType[] = []
const typesToCreate: ProductType[] = []
const typesToUpdate: ProductType[] = []
types.forEach((type) => {
const aType = existingTypesMap.get(type.value)
if (aType) {
const updatedType = manager.assign(aType, type)
typesToUpdate.push(updatedType)
} else {
const newType = manager.create(ProductType, type)
typesToCreate.push(newType)
}
})
if (typesToCreate.length) {
manager.persist(typesToCreate)
upsertedTypes.push(...typesToCreate)
}
if (typesToUpdate.length) {
manager.persist(typesToUpdate)
upsertedTypes.push(...typesToUpdate)
}
return upsertedTypes
}
}
@@ -1,22 +0,0 @@
import { ProductVariant } from "@models"
import { DALUtils } from "@medusajs/utils"
import { RequiredEntityData } from "@mikro-orm/core"
import { WithRequiredProperty } from "@medusajs/types"
import { ProductVariantServiceTypes } from "../types/services"
// eslint-disable-next-line max-len
export class ProductVariantRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
ProductVariant,
{
create: RequiredEntityData<ProductVariant>
update: WithRequiredProperty<
ProductVariantServiceTypes.UpdateProductVariantDTO,
"id"
>
}
>(ProductVariant) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,7 +1,20 @@
import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
} from "@medusajs/utils"
import { ProductCollection } from "@models"
import {
IProductCollectionRepository,
ProductCollectionServiceTypes,
} from "@types"
import {
CreateProductCollection,
UpdateProductCollection,
} from "../types/services/product-collection"
type InjectedDependencies = {
productCollectionRepository: DAL.RepositoryService
@@ -12,12 +25,12 @@ export default class ProductCollectionService<
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ProductTypes.CreateProductCollectionDTO
update: ProductTypes.UpdateProductCollectionDTO
create: CreateProductCollection
update: UpdateProductCollection
}
>(ProductCollection)<TEntity> {
// eslint-disable-next-line max-len
protected readonly productCollectionRepository_: DAL.RepositoryService<TEntity>
protected readonly productCollectionRepository_: IProductCollectionRepository<TEntity>
constructor(container: InjectedDependencies) {
super(container)
@@ -66,4 +79,40 @@ export default class ProductCollectionService<
return queryOptions
}
@InjectTransactionManager("productCollectionRepository_")
async create(
data: ProductCollectionServiceTypes.CreateProductCollection[],
context: Context = {}
): Promise<TEntity[]> {
const productCollections = data.map((collectionData) => {
if (collectionData.product_ids) {
collectionData.products = collectionData.product_ids
delete collectionData.product_ids
}
return collectionData
})
return super.create(productCollections, context)
}
@InjectTransactionManager("productCollectionRepository_")
async update(
data: ProductCollectionServiceTypes.UpdateProductCollection[],
context: Context = {}
): Promise<TEntity[]> {
const productCollections = data.map((collectionData) => {
if (collectionData.product_ids) {
collectionData.products = collectionData.product_ids
delete collectionData.product_ids
}
return collectionData
})
return super.update(productCollections, context)
}
}
+10 -15
View File
@@ -1,23 +1,18 @@
import { Image } from "@models"
import { Context, DAL } from "@medusajs/types"
import { InjectTransactionManager, MedusaContext } from "@medusajs/utils"
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
type InjectedDependencies = {
productImageRepository: DAL.RepositoryService
}
export default class ProductImageService<TEntity extends Image = Image> {
protected readonly productImageRepository_: DAL.RepositoryService
constructor({ productImageRepository }: InjectedDependencies) {
this.productImageRepository_ = productImageRepository
}
@InjectTransactionManager("productImageRepository_")
async upsert(
urls: string[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.productImageRepository_.upsert!(urls, sharedContext)
export default class ProductImageService<
TEntity extends Image = Image
> extends ModulesSdkUtils.abstractServiceFactory<InjectedDependencies>(
Image
)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,6 +1,6 @@
import { ProductOptionValue } from "@models"
import { Context, DAL } from "@medusajs/types"
import { InjectTransactionManager, MedusaContext } from "@medusajs/utils"
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { ProductOptionValueServiceTypes } from "@types"
type InjectedDependencies = {
@@ -9,30 +9,15 @@ type InjectedDependencies = {
export default class ProductOptionValueService<
TEntity extends ProductOptionValue = ProductOptionValue
> {
// eslint-disable-next-line max-len
protected readonly productOptionValueRepository_: DAL.RepositoryService<TEntity>
constructor({ productOptionValueRepository }: InjectedDependencies) {
this.productOptionValueRepository_ = productOptionValueRepository
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ProductOptionValueServiceTypes.CreateProductOptionValueDTO
update: ProductOptionValueServiceTypes.UpdateProductOptionValueDTO
}
@InjectTransactionManager("productOptionValueRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
return await this.productOptionValueRepository_.delete(ids, sharedContext)
}
@InjectTransactionManager("productOptionValueRepository_")
async upsert(
data: (
| ProductOptionValueServiceTypes.UpdateProductOptionValueDTO
| ProductOptionValueServiceTypes.CreateProductOptionValueDTO
)[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.productOptionValueRepository_.upsert!(data, sharedContext)
>(ProductOptionValue)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}
@@ -1,11 +1,7 @@
import { ProductOption } from "@models"
import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
} from "@medusajs/utils"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import { IProductOptionRepository } from "@types"
type InjectedDependencies = {
productOptionRepository: DAL.RepositoryService
@@ -20,7 +16,7 @@ export default class ProductOptionService<
update: ProductTypes.UpdateProductOptionDTO
}
>(ProductOption)<TEntity> {
protected readonly productOptionRepository_: DAL.RepositoryService<TEntity>
protected readonly productOptionRepository_: IProductOptionRepository<TEntity>
constructor(container: InjectedDependencies) {
super(container)
@@ -65,14 +61,4 @@ export default class ProductOptionService<
return queryOptions
}
@InjectTransactionManager("productOptionRepository_")
async upsert(
data:
| ProductTypes.CreateProductOptionDTO[]
| ProductTypes.UpdateProductOptionDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.productOptionRepository_.upsert!(data, sharedContext)
}
}
+4 -22
View File
@@ -1,17 +1,7 @@
import { ProductTag } from "@models"
import {
Context,
DAL,
FindConfig,
ProductTypes,
UpsertProductTagDTO,
} from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
} from "@medusajs/utils"
import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import { IProductTagRepository } from "@types"
type InjectedDependencies = {
productTagRepository: DAL.RepositoryService
@@ -26,7 +16,7 @@ export default class ProductTagService<
update: ProductTypes.UpdateProductTagDTO
}
>(ProductTag)<TEntity> {
protected readonly productTagRepository_: DAL.RepositoryService<TEntity>
protected readonly productTagRepository_: IProductTagRepository<TEntity>
constructor(container: InjectedDependencies) {
super(container)
@@ -70,12 +60,4 @@ export default class ProductTagService<
return queryOptions
}
@InjectTransactionManager("productTagRepository_")
async upsert(
data: UpsertProductTagDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.productTagRepository_.upsert!(data, sharedContext)
}
}
+4 -22
View File
@@ -1,17 +1,7 @@
import { ProductType } from "@models"
import {
Context,
DAL,
FindConfig,
ProductTypes,
UpsertProductTypeDTO,
} from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
} from "@medusajs/utils"
import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import { IProductTypeRepository } from "@types"
type InjectedDependencies = {
productTypeRepository: DAL.RepositoryService
@@ -26,7 +16,7 @@ export default class ProductTypeService<
update: ProductTypes.UpdateProductTypeDTO
}
>(ProductType)<TEntity> {
protected readonly productTypeRepository_: DAL.RepositoryService<TEntity>
protected readonly productTypeRepository_: IProductTypeRepository<TEntity>
constructor(container: InjectedDependencies) {
super(container)
@@ -71,12 +61,4 @@ export default class ProductTypeService<
return queryOptions
}
@InjectTransactionManager("productTypeRepository_")
async upsert(
types: UpsertProductTypeDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.productTypeRepository_.upsert!(types, sharedContext)
}
}
@@ -7,7 +7,7 @@ import {
} from "@medusajs/utils"
import { Product, ProductVariant } from "@models"
import { ProductVariantServiceTypes } from "@types"
import { IProductVariantRepository, ProductVariantServiceTypes } from "@types"
import ProductService from "./product"
type InjectedDependencies = {
@@ -25,7 +25,7 @@ export default class ProductVariantService<
update: ProductVariantServiceTypes.UpdateProductVariantDTO
}
>(ProductVariant)<TEntity> {
protected readonly productVariantRepository_: DAL.RepositoryService<TEntity>
protected readonly productVariantRepository_: IProductVariantRepository<TEntity>
protected readonly productService_: ProductService<TProduct>
constructor({
+2 -2
View File
@@ -1,7 +1,7 @@
import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import { Product } from "@models"
import { ProductServiceTypes } from "@types"
import { IProductRepository, ProductServiceTypes } from "@types"
type InjectedDependencies = {
productRepository: DAL.RepositoryService
@@ -16,7 +16,7 @@ export default class ProductService<
update: ProductServiceTypes.UpdateProductDTO
}
>(Product)<TEntity> {
protected readonly productRepository_: DAL.RepositoryService<TEntity>
protected readonly productRepository_: IProductRepository<TEntity>
constructor({ productRepository }: InjectedDependencies) {
// @ts-ignore
+1 -2
View File
@@ -1,5 +1,3 @@
export * from "./services"
import { IEventBusModuleService, Logger } from "@medusajs/types"
export type InitializeModuleInjectableDependencies = {
@@ -8,3 +6,4 @@ export type InitializeModuleInjectableDependencies = {
}
export * from "./services"
export * from "./repositories"
+100
View File
@@ -0,0 +1,100 @@
import { DAL, ProductTypes, WithRequiredProperty } from "@medusajs/types"
import {
Image,
Product,
ProductCollection,
ProductOption,
ProductOptionValue,
ProductTag,
ProductType,
ProductVariant,
} from "@models"
import { UpdateProductDTO } from "./services/product"
import {
CreateProductCollection,
UpdateProductCollection,
} from "./services/product-collection"
import {
CreateProductOptionValueDTO,
UpdateProductOptionValueDTO,
} from "./services/product-option-value"
import { UpdateProductVariantDTO } from "./services/product-variant"
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductRepository<TEntity extends Product = Product>
extends DAL.RepositoryService<
TEntity,
{
create: WithRequiredProperty<ProductTypes.CreateProductOnlyDTO, "status">
update: WithRequiredProperty<UpdateProductDTO, "id">
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductCollectionRepository<
TEntity extends ProductCollection = ProductCollection
> extends DAL.RepositoryService<
TEntity,
{
create: CreateProductCollection
update: UpdateProductCollection
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductImageRepository<TEntity extends Image = Image>
extends DAL.RepositoryService<TEntity> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductOptionRepository<
TEntity extends ProductOption = ProductOption
> extends DAL.RepositoryService<
TEntity,
{
create: ProductTypes.CreateProductOptionDTO
update: ProductTypes.UpdateProductOptionDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductOptionValueRepository<
TEntity extends ProductOptionValue = ProductOptionValue
> extends DAL.RepositoryService<
TEntity,
{
create: CreateProductOptionValueDTO
update: UpdateProductOptionValueDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductTagRepository<TEntity extends ProductTag = ProductTag>
extends DAL.RepositoryService<
TEntity,
{
create: ProductTypes.CreateProductTagDTO
update: ProductTypes.UpdateProductTagDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductTypeRepository<
TEntity extends ProductType = ProductType
> extends DAL.RepositoryService<
TEntity,
{
create: ProductTypes.CreateProductTypeDTO
update: ProductTypes.UpdateProductTypeDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductVariantRepository<
TEntity extends ProductVariant = ProductVariant
> extends DAL.RepositoryService<
TEntity,
{
create: ProductTypes.CreateProductVariantOnlyDTO
update: UpdateProductVariantDTO
}
> {}
@@ -1,3 +1,5 @@
import { ProductTypes } from "@medusajs/types"
export type ProductCollectionEventData = {
id: string
}
@@ -7,3 +9,13 @@ export enum ProductCollectionEvents {
COLLECTION_CREATED = "product-collection.created",
COLLECTION_DELETED = "product-collection.deleted",
}
export type UpdateProductCollection =
ProductTypes.UpdateProductCollectionDTO & {
products?: string[]
}
export type CreateProductCollection =
ProductTypes.CreateProductCollectionDTO & {
products?: string[]
}