feat: Product module events (#7598)

WIP, not ready to review

**what**
- add events
- integration tests of emitted events
- remove integration tests on auto generated services in favor of module method integration tests
This commit is contained in:
Adrien de Peretti
2024-06-06 13:47:38 +02:00
committed by GitHub
parent c3b6fc1d8e
commit 3fbb8aa671
20 changed files with 292 additions and 1756 deletions

View File

@@ -0,0 +1,15 @@
import { buildEventNamesFromEntityName } from "../event-bus"
import { Modules } from "../modules-sdk"
const eventBaseNames: [
"product",
"productVariant",
"productOption",
"productType",
"productTag"
] = ["product", "productVariant", "productOption", "productType", "productTag"]
export const ProductEvents = buildEventNamesFromEntityName(
eventBaseNames,
Modules.PRODUCT
)

View File

@@ -4,3 +4,5 @@ export enum ProductStatus {
PUBLISHED = "published",
REJECTED = "rejected",
}
export * from "./events"

View File

@@ -1,28 +1,29 @@
import { ProductCategoryService } from "@services"
import { Modules } from "@medusajs/modules-sdk"
import { IProductModuleService } from "@medusajs/types"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import { createProductCategories } from "../../../__fixtures__/product-category"
import { moduleIntegrationTestRunner } from "medusa-test-utils"
import { createProductCategories } from "../__fixtures__/product-category"
import {
eletronicsCategoriesData,
productCategoriesData,
productCategoriesRankData,
} from "../../../__fixtures__/product-category/data"
} from "../__fixtures__/product-category/data"
import { IProductModuleService } from "@medusajs/types"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
type Service = IProductModuleService & {
productCategoryService_: ProductCategoryService
}
moduleIntegrationTestRunner<Service>({
moduleName: Modules.PRODUCT,
testSuite: ({
MikroOrmWrapper,
medusaApp,
}: SuiteOptions<IProductModuleService>) => {
testSuite: ({ MikroOrmWrapper, service: moduleService }) => {
describe("Product category Service", () => {
let service: ProductCategoryService
beforeEach(() => {
service = medusaApp.modules["productService"].productCategoryService_
service = moduleService.productCategoryService_
})
describe("list", () => {

View File

@@ -4,23 +4,19 @@ import { ProductStatus } from "@medusajs/utils"
import { Product, ProductCategory } from "@models"
import {
MockEventBusService,
SuiteOptions,
moduleIntegrationTestRunner,
} from "medusa-test-utils"
import { createProductCategories } from "../../../__fixtures__/product-category"
import { productCategoriesRankData } from "../../../__fixtures__/product-category/data"
import { createProductCategories } from "../../__fixtures__/product-category"
import { productCategoriesRankData } from "../../__fixtures__/product-category/data"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IProductModuleService>({
moduleName: Modules.PRODUCT,
injectedDependencies: {
eventBusModuleService: new MockEventBusService(),
},
testSuite: ({
MikroOrmWrapper,
service,
}: SuiteOptions<IProductModuleService>) => {
testSuite: ({ MikroOrmWrapper, service }) => {
describe("ProductModuleService product categories", () => {
let productOne: Product
let productTwo: Product

View File

@@ -4,22 +4,18 @@ import { ProductStatus } from "@medusajs/utils"
import { Product, ProductCollection } from "@models"
import {
MockEventBusService,
SuiteOptions,
moduleIntegrationTestRunner,
} from "medusa-test-utils"
import { createCollections } from "../../../__fixtures__/product"
import { createCollections } from "../../__fixtures__/product"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IProductModuleService>({
moduleName: Modules.PRODUCT,
injectedDependencies: {
eventBusModuleService: new MockEventBusService(),
},
testSuite: ({
MikroOrmWrapper,
service,
}: SuiteOptions<IProductModuleService>) => {
testSuite: ({ MikroOrmWrapper, service }) => {
describe("ProductModuleService product collections", () => {
let productOne: Product
let productTwo: Product

View File

@@ -2,16 +2,13 @@ import { Modules } from "@medusajs/modules-sdk"
import { IProductModuleService } from "@medusajs/types"
import { ProductStatus } from "@medusajs/utils"
import { Product, ProductOption } from "@models"
import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils"
import { moduleIntegrationTestRunner } from "medusa-test-utils"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IProductModuleService>({
moduleName: Modules.PRODUCT,
testSuite: ({
MikroOrmWrapper,
service,
}: SuiteOptions<IProductModuleService>) => {
testSuite: ({ MikroOrmWrapper, service }) => {
describe("ProductModuleService product options", () => {
let optionOne: ProductOption
let optionTwo: ProductOption

View File

@@ -2,16 +2,13 @@ import { Modules } from "@medusajs/modules-sdk"
import { IProductModuleService } from "@medusajs/types"
import { ProductStatus } from "@medusajs/utils"
import { Product, ProductTag } from "@models"
import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils"
import { moduleIntegrationTestRunner } from "medusa-test-utils"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IProductModuleService>({
moduleName: Modules.PRODUCT,
testSuite: ({
MikroOrmWrapper,
service,
}: SuiteOptions<IProductModuleService>) => {
testSuite: ({ MikroOrmWrapper, service }) => {
describe("ProductModuleService product tags", () => {
let tagOne: ProductTag
let tagTwo: ProductTag

View File

@@ -1,16 +1,13 @@
import { Modules } from "@medusajs/modules-sdk"
import { IProductModuleService } from "@medusajs/types"
import { ProductType } from "@models"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import { moduleIntegrationTestRunner } from "medusa-test-utils"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IProductModuleService>({
moduleName: Modules.PRODUCT,
testSuite: ({
MikroOrmWrapper,
service,
}: SuiteOptions<IProductModuleService>) => {
testSuite: ({ MikroOrmWrapper, service }) => {
describe("ProductModuleService product types", () => {
let typeOne: ProductType
let typeTwo: ProductType

View File

@@ -1,23 +1,43 @@
import { Modules } from "@medusajs/modules-sdk"
import { IProductModuleService } from "@medusajs/types"
import { ProductStatus } from "@medusajs/utils"
import { Product, ProductVariant } from "@models"
import {
CreateProductDTO,
CreateProductVariantDTO,
IProductModuleService,
ProductDTO,
ProductVariantDTO,
} from "@medusajs/types"
import {
CommonEvents,
composeMessage,
ProductEvents,
ProductStatus,
} from "@medusajs/utils"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import {
MockEventBusService,
moduleIntegrationTestRunner,
} from "medusa-test-utils"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IProductModuleService>({
moduleName: Modules.PRODUCT,
testSuite: ({
MikroOrmWrapper,
service,
}: SuiteOptions<IProductModuleService>) => {
testSuite: ({ service }) => {
let eventBusEmitSpy
beforeEach(() => {
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
})
afterEach(() => {
jest.clearAllMocks()
})
describe("ProductModuleService product variants", () => {
let variantOne: ProductVariant
let variantTwo: ProductVariant
let productOne: Product
let productTwo: Product
let variantOne: ProductVariantDTO
let variantTwo: ProductVariantDTO
let productOne: ProductDTO
let productTwo: ProductDTO
beforeEach(async () => {
productOne = await service.create({
@@ -34,26 +54,28 @@ moduleIntegrationTestRunner({
values: ["red", "blue"],
},
],
})
} as CreateProductDTO)
productTwo = await service.create({
id: "product-2",
title: "product 2",
status: ProductStatus.PUBLISHED,
})
} as CreateProductDTO)
variantOne = await service.createVariants({
id: "test-1",
title: "variant 1",
product_id: productOne.id,
options: { size: "large" },
})
} as CreateProductVariantDTO)
variantTwo = await service.createVariants({
id: "test-2",
title: "variant",
product_id: productTwo.id,
})
} as CreateProductVariantDTO)
jest.clearAllMocks()
})
describe("listAndCountVariants", () => {
@@ -183,6 +205,16 @@ moduleIntegrationTestRunner({
const productVariant = await service.retrieveVariant(variantOne.id)
expect(productVariant.title).toEqual("new test")
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
composeMessage(ProductEvents.product_variant_updated, {
data: { id: variantOne.id },
object: "product_variant",
service: Modules.PRODUCT,
action: CommonEvents.UPDATED,
}),
])
})
it("should upsert the options of a variant successfully", async () => {
@@ -203,6 +235,16 @@ moduleIntegrationTestRunner({
}),
])
)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
composeMessage(ProductEvents.product_variant_updated, {
data: { id: variantOne.id },
object: "product_variant",
service: Modules.PRODUCT,
action: CommonEvents.UPDATED,
}),
])
})
it("should do a partial update on the options of a variant successfully", async () => {
@@ -241,6 +283,42 @@ moduleIntegrationTestRunner({
})
})
describe("createVariants", () => {
it("should create variants successfully", async () => {
jest.clearAllMocks()
const data: CreateProductVariantDTO = {
title: "variant 3",
product_id: productOne.id,
options: { size: "small" },
}
const variant = await service.createVariants(data)
expect(variant).toEqual(
expect.objectContaining({
title: "variant 3",
product_id: productOne.id,
options: expect.arrayContaining([
expect.objectContaining({
value: "small",
}),
]),
})
)
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
expect(eventBusEmitSpy).toHaveBeenCalledWith([
composeMessage(ProductEvents.product_variant_created, {
data: { id: variant.id },
object: "product_variant",
service: Modules.PRODUCT,
action: CommonEvents.CREATED,
}),
])
})
})
describe("softDelete variant", () => {
it("should soft delete a variant and its relations", async () => {
const beforeDeletedVariants = await service.listVariants(

View File

@@ -12,23 +12,22 @@ import { UpdateProductInput } from "@types"
import {
MockEventBusService,
moduleIntegrationTestRunner,
SuiteOptions,
} from "medusa-test-utils"
import { createCollections, createTypes } from "../../../__fixtures__/product"
import { createProductCategories } from "../../../__fixtures__/product-category"
import { buildProductAndRelationsData } from "../../../__fixtures__/product/data/create-product"
import {
buildProductAndRelationsData,
createCollections,
createTypes,
} from "../../__fixtures__/product"
import { createProductCategories } from "../../__fixtures__/product-category"
jest.setTimeout(300000)
moduleIntegrationTestRunner({
moduleIntegrationTestRunner<IProductModuleService>({
moduleName: Modules.PRODUCT,
injectedDependencies: {
eventBusModuleService: new MockEventBusService(),
},
testSuite: ({
MikroOrmWrapper,
service,
}: SuiteOptions<IProductModuleService>) => {
testSuite: ({ MikroOrmWrapper, service }) => {
describe("ProductModuleService products", function () {
let productCollectionOne: ProductCollection
let productCollectionTwo: ProductCollection

View File

@@ -6,33 +6,34 @@ import {
createImages,
createProductAndTags,
createProductVariants,
} from "../../../__fixtures__/product"
} from "../__fixtures__/product"
import { Modules } from "@medusajs/modules-sdk"
import { IProductModuleService, ProductDTO } from "@medusajs/types"
import { ProductStatus, kebabCase } from "@medusajs/utils"
import { kebabCase, ProductStatus } from "@medusajs/utils"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { ProductService } from "@services"
import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils"
import { createProductCategories } from "../../../__fixtures__/product-category"
import { moduleIntegrationTestRunner } from "medusa-test-utils"
import { createProductCategories } from "../__fixtures__/product-category"
import {
categoriesData,
productsData,
variantsData,
} from "../../../__fixtures__/product/data"
} from "../__fixtures__/product/data"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
type Service = IProductModuleService & {
productService_: ProductService
}
moduleIntegrationTestRunner<Service>({
moduleName: Modules.PRODUCT,
testSuite: ({
MikroOrmWrapper,
medusaApp,
}: SuiteOptions<IProductModuleService>) => {
testSuite: ({ MikroOrmWrapper, service: moduleService }) => {
let service: ProductService
beforeEach(() => {
service = medusaApp.modules["productService"].productService_
service = moduleService.productService_
})
describe("Product Service", () => {

View File

@@ -1,370 +0,0 @@
import { ProductCollectionService } from "@services"
import { createCollections } from "../../../__fixtures__/product"
import { Modules } from "@medusajs/modules-sdk"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import { IProductModuleService } from "@medusajs/types"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
moduleName: Modules.PRODUCT,
testSuite: ({
MikroOrmWrapper,
medusaApp,
}: SuiteOptions<IProductModuleService>) => {
describe("Product collection Service", () => {
let service: ProductCollectionService
beforeEach(() => {
service = medusaApp.modules["productService"].productCollectionService_
})
describe("list", () => {
const data = [
{
id: "test-1",
title: "col 1",
},
{
id: "test-2",
title: "col 2",
},
{
id: "test-3",
title: "col 3 extra",
},
{
id: "test-4",
title: "col 4 extra",
},
]
beforeEach(async () => {
await createCollections(MikroOrmWrapper.forkManager(), data)
})
it("list product collections", async () => {
const productCollectionResults = await service.list()
expect(productCollectionResults).toEqual([
expect.objectContaining({
id: "test-1",
title: "col 1",
}),
expect.objectContaining({
id: "test-2",
title: "col 2",
}),
expect.objectContaining({
id: "test-3",
title: "col 3 extra",
}),
expect.objectContaining({
id: "test-4",
title: "col 4 extra",
}),
])
})
it("list product collections by id", async () => {
const productCollectionResults = await service.list({
id: data![0].id,
})
expect(productCollectionResults).toEqual([
expect.objectContaining({
id: "test-1",
title: "col 1",
}),
])
})
it("list product collections by title matching string", async () => {
const productCollectionResults = await service.list({
title: "col 3 extra",
})
expect(productCollectionResults).toEqual([
expect.objectContaining({
id: "test-3",
title: "col 3 extra",
}),
])
})
})
describe("listAndCount", () => {
const data = [
{
id: "test-1",
title: "col 1",
},
{
id: "test-2",
title: "col 2",
},
{
id: "test-3",
title: "col 3 extra",
},
{
id: "test-4",
title: "col 4 extra",
},
]
beforeEach(async () => {
await createCollections(MikroOrmWrapper.forkManager(), data)
})
it("should return all collections and count", async () => {
const [productCollectionResults, count] = await service.listAndCount()
const serialized = JSON.parse(
JSON.stringify(productCollectionResults)
)
expect(serialized).toEqual([
expect.objectContaining({
id: "test-1",
title: "col 1",
}),
expect.objectContaining({
id: "test-2",
title: "col 2",
}),
expect.objectContaining({
id: "test-3",
title: "col 3 extra",
}),
expect.objectContaining({
id: "test-4",
title: "col 4 extra",
}),
])
})
it("should return count and collections based on filter data", async () => {
const [productCollectionResults, count] = await service.listAndCount({
id: data![0].id,
})
const serialized = JSON.parse(
JSON.stringify(productCollectionResults)
)
expect(count).toEqual(1)
expect(serialized).toEqual([
expect.objectContaining({
id: "test-1",
title: "col 1",
}),
])
})
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 serialized = JSON.parse(
JSON.stringify(productCollectionResults)
)
expect(count).toEqual(4)
expect(serialized).toEqual([
{
id: "test-2",
title: "col 2",
handle: "col-2",
products: [],
},
])
})
})
describe("retrieve", () => {
const collectionData = {
id: "collection-1",
title: "collection 1",
}
beforeEach(async () => {
await createCollections(MikroOrmWrapper.forkManager(), [
collectionData,
])
})
it("should return collection for the given id", async () => {
const productCollectionResults = await service.retrieve(
collectionData.id
)
expect(productCollectionResults).toEqual(
expect.objectContaining({
id: collectionData.id,
})
)
})
it("should throw an error when collection with id does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
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 () => {
let error
try {
await service.retrieve(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual(
"productCollection - id must be defined"
)
})
it("should return collection based on config select param", async () => {
const productCollectionResults = await service.retrieve(
collectionData.id,
{
select: ["id", "title"],
}
)
const serialized = JSON.parse(
JSON.stringify(productCollectionResults)
)
expect(serialized).toEqual({
id: collectionData.id,
title: collectionData.title,
handle: "collection-1",
})
})
it("should return collection based on config relation param", async () => {
const productCollectionResults = await service.retrieve(
collectionData.id,
{
select: ["id", "title"],
relations: ["products"],
}
)
const serialized = JSON.parse(
JSON.stringify(productCollectionResults)
)
expect(serialized).toEqual({
id: collectionData.id,
title: collectionData.title,
handle: "collection-1",
products: [],
})
})
})
describe("delete", () => {
const collectionId = "collection-1"
const collectionData = {
id: collectionId,
title: "collection 1",
}
beforeEach(async () => {
await createCollections(MikroOrmWrapper.forkManager(), [
collectionData,
])
})
it("should delete the product collection given an ID successfully", async () => {
await service.delete([collectionId])
const collections = await service.list({
id: collectionId,
})
expect(collections).toHaveLength(0)
})
})
describe("update", () => {
const collectionId = "collection-1"
const collectionData = {
id: collectionId,
title: "collection 1",
}
beforeEach(async () => {
await createCollections(MikroOrmWrapper.forkManager(), [
collectionData,
])
})
it("should update the value of the collection successfully", async () => {
await service.update([
{
id: collectionId,
title: "New Collection",
},
])
const productCollection = await service.retrieve(collectionId)
expect(productCollection.title).toEqual("New Collection")
})
it("should throw an error when an id does not exist", async () => {
let error
try {
await service.update([
{
id: "does-not-exist",
title: "New Collection",
},
])
} catch (e) {
error = e
}
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",
},
])
const [productCollection] = await service.list({
title: "New Collection",
})
expect(productCollection.title).toEqual("New Collection")
})
})
})
},
})

View File

@@ -1,369 +0,0 @@
import { Modules } from "@medusajs/modules-sdk"
import { IProductModuleService } from "@medusajs/types"
import { ProductStatus } from "@medusajs/utils"
import { Product } from "@models"
import { ProductOptionService } from "@services"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import { createOptions } from "../../../__fixtures__/product"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
moduleName: Modules.PRODUCT,
testSuite: ({
MikroOrmWrapper,
medusaApp,
}: SuiteOptions<IProductModuleService>) => {
describe("ProductOption Service", () => {
let service: ProductOptionService
beforeEach(() => {
service = medusaApp.modules["productService"].productOptionService_
})
let productOne: Product
let productTwo: Product
const productOneData = {
id: "product-1",
title: "product 1",
status: ProductStatus.PUBLISHED,
}
const productTwoData = {
id: "product-2",
title: "product 2",
status: ProductStatus.PUBLISHED,
}
beforeEach(async () => {
const testManager = MikroOrmWrapper.forkManager()
productOne = testManager.create(Product, productOneData)
productTwo = testManager.create(Product, productTwoData)
await createOptions(testManager, [
{
id: "option-1",
title: "Option 1",
product: productOne,
},
{
id: "option-2",
title: "Option 2",
product: productOne,
},
])
})
describe("list", () => {
it("list product option", async () => {
const optionResults = await service.list()
expect(optionResults).toEqual([
expect.objectContaining({
id: "option-1",
title: "Option 1",
}),
expect.objectContaining({
id: "option-2",
title: "Option 2",
}),
])
})
it("list product option by id", async () => {
const optionResults = await service.list({ id: "option-2" })
expect(optionResults).toEqual([
expect.objectContaining({
id: "option-2",
title: "Option 2",
}),
])
})
it("list product option by title matching string", async () => {
const optionResults = await service.list({ title: "Option 1" })
expect(optionResults).toEqual([
expect.objectContaining({
id: "option-1",
title: "Option 1",
}),
])
})
})
describe("listAndCount", () => {
it("should return product option and count", async () => {
const [optionResults, count] = await service.listAndCount()
expect(count).toEqual(2)
expect(optionResults).toEqual([
expect.objectContaining({
id: "option-1",
title: "Option 1",
}),
expect.objectContaining({
id: "option-2",
title: "Option 2",
}),
])
})
it("should return product option and count when filtered", async () => {
const [optionResults, count] = await service.listAndCount({
id: "option-2",
})
expect(count).toEqual(1)
expect(optionResults).toEqual([
expect.objectContaining({
id: "option-2",
}),
])
})
it("should return product option and count when using skip and take", async () => {
const [optionResults, count] = await service.listAndCount(
{},
{ skip: 1, take: 1 }
)
expect(count).toEqual(2)
expect(optionResults).toEqual([
expect.objectContaining({
id: "option-2",
}),
])
})
it("should return requested fields", async () => {
const [optionResults, count] = await service.listAndCount(
{},
{
take: 1,
select: ["title"],
}
)
const serialized = JSON.parse(JSON.stringify(optionResults))
expect(count).toEqual(2)
expect(serialized).toEqual([
expect.objectContaining({
id: "option-1",
}),
])
})
})
describe("retrieve", () => {
const optionId = "option-1"
const optionValue = "Option 1"
it("should return option for the given id", async () => {
const option = await service.retrieve(optionId)
expect(option).toEqual(
expect.objectContaining({
id: optionId,
})
)
})
it("should throw an error when option with id does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"ProductOption with id: does-not-exist was not found"
)
})
it("should throw an error when an id is not provided", async () => {
let error
try {
await service.retrieve(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual("productOption - id must be defined")
})
it("should return option based on config select param", async () => {
const option = await service.retrieve(optionId, {
select: ["id", "title"],
})
const serialized = JSON.parse(JSON.stringify(option))
expect(serialized).toEqual({
id: optionId,
title: optionValue,
product_id: null,
})
})
})
describe("delete", () => {
const optionId = "option-1"
it("should delete the product option given an ID successfully", async () => {
await service.delete([optionId])
const options = await service.list({
id: optionId,
})
expect(options).toHaveLength(0)
})
})
describe("update", () => {
const optionId = "option-1"
it("should update the title of the option successfully", async () => {
await service.update([
{
id: optionId,
title: "UK",
},
])
const productOption = await service.retrieve(optionId)
expect(productOption.title).toEqual("UK")
})
it("should update the relationship of the option successfully", async () => {
await service.update([
{
id: optionId,
product_id: productTwo.id,
},
])
const productOption = await service.retrieve(optionId, {
relations: ["product"],
})
expect(productOption).toEqual(
expect.objectContaining({
id: optionId,
product: expect.objectContaining({
id: productTwo.id,
}),
})
)
})
it("should throw an error when an id does not exist", async () => {
let error
try {
await service.update([
{
id: "does-not-exist",
title: "UK",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual(
'ProductOption with id "does-not-exist" not found'
)
})
})
describe("create", () => {
it("should create a option successfully", async () => {
await service.create([
{
title: "UK",
product: productOne,
},
])
const [productOption] = await service.list(
{
title: "UK",
},
{
relations: ["product"],
}
)
expect(productOption).toEqual(
expect.objectContaining({
title: "UK",
product: expect.objectContaining({
id: productOne.id,
}),
})
)
})
})
describe("upsert", function () {
it("should create an option and update another option successfully", async () => {
const productOption = (
await service.create([
{
title: "UK",
product: productOne,
},
])
)[0]
const optionToUpdate = {
id: productOption.id,
title: "US",
}
const newOption = {
title: "US2",
product_id: productOne.id,
}
await service.upsert([optionToUpdate, newOption])
const productOptions = await service.list(
{
q: "US%",
},
{
relations: ["product"],
}
)
expect(JSON.parse(JSON.stringify(productOptions))).toEqual(
expect.arrayContaining([
expect.objectContaining({
title: "US",
product: expect.objectContaining({
id: productOne.id,
}),
}),
expect.objectContaining({
title: newOption.title,
product: expect.objectContaining({
id: productOne.id,
}),
}),
])
)
})
})
})
},
})

View File

@@ -1,336 +0,0 @@
import { Modules } from "@medusajs/modules-sdk"
import { IProductModuleService, ModulesSdkTypes } from "@medusajs/types"
import { ProductStatus } from "@medusajs/utils"
import { Product, ProductTag } from "@models"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import { createProductAndTags } from "../../../__fixtures__/product"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
moduleName: Modules.PRODUCT,
testSuite: ({
MikroOrmWrapper,
medusaApp,
}: SuiteOptions<IProductModuleService>) => {
describe("ProductTag Service", () => {
let data!: Product[]
let service: ModulesSdkTypes.InternalModuleService<ProductTag>
beforeEach(() => {
service = medusaApp.modules["productService"].productTagService_
})
const productsData = [
{
id: "test-1",
title: "product 1",
status: ProductStatus.PUBLISHED,
tags: [
{
id: "tag-1",
value: "France",
},
],
},
{
id: "test-2",
title: "product",
status: ProductStatus.PUBLISHED,
tags: [
{
id: "tag-2",
value: "Germany",
},
{
id: "tag-3",
value: "United States",
},
{
id: "tag-4",
value: "United Kingdom",
},
],
},
]
beforeEach(async () => {
data = await createProductAndTags(
MikroOrmWrapper.forkManager(),
productsData
)
})
describe("list", () => {
it("list product tags", async () => {
const tagsResults = await service.list()
expect(tagsResults).toEqual([
expect.objectContaining({
id: "tag-1",
value: "France",
}),
expect.objectContaining({
id: "tag-2",
value: "Germany",
}),
expect.objectContaining({
id: "tag-3",
value: "United States",
}),
expect.objectContaining({
id: "tag-4",
value: "United Kingdom",
}),
])
})
it("list product tags by id", async () => {
const tagsResults = await service.list({ id: data[0].tags![0].id })
expect(tagsResults).toEqual([
expect.objectContaining({
id: "tag-1",
value: "France",
}),
])
})
it("list product tags by value matching string", async () => {
const tagsResults = await service.list({ q: "united kingdom" })
expect(tagsResults).toEqual([
expect.objectContaining({
id: "tag-4",
value: "United Kingdom",
}),
])
})
})
describe("listAndCount", () => {
it("should return product tags and count", async () => {
const [tagsResults, count] = await service.listAndCount()
expect(count).toEqual(4)
expect(tagsResults).toEqual([
expect.objectContaining({
id: "tag-1",
value: "France",
}),
expect.objectContaining({
id: "tag-2",
value: "Germany",
}),
expect.objectContaining({
id: "tag-3",
value: "United States",
}),
expect.objectContaining({
id: "tag-4",
value: "United Kingdom",
}),
])
})
it("should return product tags and count when filtered", async () => {
const [tagsResults, count] = await service.listAndCount({
id: data[0].tags![0].id,
})
expect(count).toEqual(1)
expect(tagsResults).toEqual([
expect.objectContaining({
id: "tag-1",
}),
])
})
it("should return product tags and count when using skip and take", async () => {
const [tagsResults, count] = await service.listAndCount(
{},
{ skip: 1, take: 2 }
)
expect(count).toEqual(4)
expect(tagsResults).toEqual([
expect.objectContaining({
id: "tag-2",
}),
expect.objectContaining({
id: "tag-3",
}),
])
})
it("should return requested fields and relations", async () => {
const [tagsResults, count] = await service.listAndCount(
{},
{
take: 1,
select: ["value", "products.id"],
relations: ["products"],
}
)
const serialized = JSON.parse(JSON.stringify(tagsResults))
expect(count).toEqual(4)
expect(serialized).toEqual([
expect.objectContaining({
id: "tag-1",
products: [
{
id: "test-1",
collection_id: null,
type_id: null,
},
],
value: "France",
}),
])
})
})
describe("retrieve", () => {
const tagId = "tag-1"
const tagValue = "France"
const productId = "test-1"
it("should return tag for the given id", async () => {
const tag = await service.retrieve(tagId)
expect(tag).toEqual(
expect.objectContaining({
id: tagId,
})
)
})
it("should throw an error when tag with id does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
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 () => {
let error
try {
await service.retrieve(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual("productTag - id must be defined")
})
it("should return tag based on config select param", async () => {
const tag = await service.retrieve(tagId, {
select: ["id", "value"],
})
const serialized = JSON.parse(JSON.stringify(tag))
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 serialized = JSON.parse(JSON.stringify(tag))
expect(serialized).toEqual({
id: tagId,
value: tagValue,
products: [
expect.objectContaining({
id: productId,
}),
],
})
})
})
describe("delete", () => {
const tagId = "tag-1"
it("should delete the product tag given an ID successfully", async () => {
await service.delete([tagId])
const tags = await service.list({
id: tagId,
})
expect(tags).toHaveLength(0)
})
})
describe("update", () => {
const tagId = "tag-1"
it("should update the value of the tag successfully", async () => {
await service.update([
{
id: tagId,
value: "UK",
},
])
const productTag = await service.retrieve(tagId)
expect(productTag.value).toEqual("UK")
})
it("should throw an error when an id does not exist", async () => {
let error
try {
await service.update([
{
id: "does-not-exist",
value: "UK",
},
])
} catch (e) {
error = e
}
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",
},
])
const [productTag] = await service.list({
value: "UK",
})
expect(productTag.value).toEqual("UK")
})
})
})
},
})

View File

@@ -1,276 +0,0 @@
import { Modules } from "@medusajs/modules-sdk"
import { IProductModuleService } from "@medusajs/types"
import { ProductStatus } from "@medusajs/utils"
import { Product } from "@models"
import { ProductTypeService } from "@services"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
import { createProductAndTypes } from "../../../__fixtures__/product"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
moduleName: Modules.PRODUCT,
testSuite: ({
MikroOrmWrapper,
medusaApp,
}: SuiteOptions<IProductModuleService>) => {
describe("ProductType Service", () => {
let data!: Product[]
let service: ProductTypeService
beforeEach(() => {
service = medusaApp.modules["productService"].productTypeService_
})
const productsData = [
{
id: "product-1",
title: "product 1",
status: ProductStatus.PUBLISHED,
type: {
id: "type-1",
value: "Type 1",
},
},
{
id: "product-2",
title: "product",
status: ProductStatus.PUBLISHED,
type: {
id: "type-2",
value: "Type 2",
},
},
]
beforeEach(async () => {
data = await createProductAndTypes(
MikroOrmWrapper.forkManager(),
productsData
)
})
describe("list", () => {
it("list product type", async () => {
const typeResults = await service.list()
expect(typeResults).toEqual([
expect.objectContaining({
id: "type-1",
value: "Type 1",
}),
expect.objectContaining({
id: "type-2",
value: "Type 2",
}),
])
})
it("list product type by id", async () => {
const typeResults = await service.list({ id: data[0].type.id })
expect(typeResults).toEqual([
expect.objectContaining({
id: "type-1",
value: "Type 1",
}),
])
})
it("list product type by value matching string", async () => {
const typeResults = await service.list({ value: "Type 1" })
expect(typeResults).toEqual([
expect.objectContaining({
id: "type-1",
value: "Type 1",
}),
])
})
})
describe("listAndCount", () => {
it("should return product type and count", async () => {
const [typeResults, count] = await service.listAndCount()
expect(count).toEqual(2)
expect(typeResults).toEqual([
expect.objectContaining({
id: "type-1",
value: "Type 1",
}),
expect.objectContaining({
id: "type-2",
value: "Type 2",
}),
])
})
it("should return product type and count when filtered", async () => {
const [typeResults, count] = await service.listAndCount({
id: data[0].type.id,
})
expect(count).toEqual(1)
expect(typeResults).toEqual([
expect.objectContaining({
id: "type-1",
}),
])
})
it("should return product type and count when using skip and take", async () => {
const [typeResults, count] = await service.listAndCount(
{},
{ skip: 1, take: 1 }
)
expect(count).toEqual(2)
expect(typeResults).toEqual([
expect.objectContaining({
id: "type-2",
}),
])
})
it("should return requested fields", async () => {
const [typeResults, count] = await service.listAndCount(
{},
{
take: 1,
select: ["value"],
}
)
const serialized = JSON.parse(JSON.stringify(typeResults))
expect(count).toEqual(2)
expect(serialized).toEqual([
expect.objectContaining({
id: "type-1",
}),
])
})
})
describe("retrieve", () => {
const typeId = "type-1"
const typeValue = "Type 1"
it("should return type for the given id", async () => {
const type = await service.retrieve(typeId)
expect(type).toEqual(
expect.objectContaining({
id: typeId,
})
)
})
it("should throw an error when type with id does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
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 () => {
let error
try {
await service.retrieve(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual("productType - id must be defined")
})
it("should return type based on config select param", async () => {
const type = await service.retrieve(typeId, {
select: ["id", "value"],
})
const serialized = JSON.parse(JSON.stringify(type))
expect(serialized).toEqual({
id: typeId,
value: typeValue,
})
})
})
describe("delete", () => {
const typeId = "type-1"
it("should delete the product type given an ID successfully", async () => {
await service.delete([typeId])
const types = await service.list({
id: typeId,
})
expect(types).toHaveLength(0)
})
})
describe("update", () => {
const typeId = "type-1"
it("should update the value of the type successfully", async () => {
await service.update([
{
id: typeId,
value: "UK",
},
])
const productType = await service.retrieve(typeId)
expect(productType.value).toEqual("UK")
})
it("should throw an error when an id does not exist", async () => {
let error
try {
await service.update([
{
id: "does-not-exist",
value: "UK",
},
])
} catch (e) {
error = e
}
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",
},
])
const [productType] = await service.list({
value: "UK",
})
expect(productType.value).toEqual("UK")
})
})
})
},
})

View File

@@ -1,321 +0,0 @@
import { InternalModuleService, IProductModuleService } from "@medusajs/types"
import { ProductStatus } from "@medusajs/utils"
import { Collection } from "@mikro-orm/core"
import { Product, ProductOption, ProductTag, ProductVariant } from "@models"
import {
createOptions,
createProductAndTags,
createProductVariants,
} from "../../../__fixtures__/product"
import { productsData, variantsData } from "../../../__fixtures__/product/data"
import { buildProductVariantOnlyData } from "../../../__fixtures__/variant/data/create-variant"
import { Modules } from "@medusajs/modules-sdk"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
jest.setTimeout(30000)
moduleIntegrationTestRunner({
moduleName: Modules.PRODUCT,
testSuite: ({
MikroOrmWrapper,
medusaApp,
}: SuiteOptions<IProductModuleService>) => {
describe.skip("ProductVariant Service", () => {
let variantOne: ProductVariant
let variantTwo: ProductVariant
let productOne: Product
const productVariantTestOne = "test-1"
let service: InternalModuleService<any>
beforeEach(() => {
service = medusaApp.modules["productService"].productVariantService_
})
describe("list", () => {
beforeEach(async () => {
const testManager = await MikroOrmWrapper.forkManager()
productOne = testManager.create(Product, {
id: "product-1",
title: "product 1",
status: ProductStatus.PUBLISHED,
})
variantOne = testManager.create(ProductVariant, {
id: productVariantTestOne,
title: "variant 1",
product: productOne,
})
variantTwo = testManager.create(ProductVariant, {
id: "test-2",
title: "variant",
product: productOne,
})
await testManager.persistAndFlush([variantOne, variantTwo])
})
it("selecting by properties, scopes out the results", async () => {
const results = await service.list({
id: variantOne.id,
})
expect(results).toEqual([
expect.objectContaining({
id: variantOne.id,
title: "variant 1",
}),
])
})
it("passing a limit, scopes the result to the limit", async () => {
const results = await service.list(
{},
{
take: 1,
}
)
expect(results).toEqual([
expect.objectContaining({
id: variantOne.id,
}),
])
})
it("passing populate, scopes the results of the response", async () => {
const results = await service.list(
{
id: productVariantTestOne,
},
{
select: ["id", "title", "product.title"] as any,
relations: ["product"],
}
)
expect(results).toEqual([
expect.objectContaining({
id: productVariantTestOne,
title: "variant 1",
product: expect.objectContaining({
id: "product-1",
title: "product 1",
tags: expect.any(Collection<ProductTag>),
variants: expect.any(Collection<ProductVariant>),
}),
}),
])
expect(JSON.parse(JSON.stringify(results))).toEqual([
{
id: productVariantTestOne,
title: "variant 1",
product: {
id: "product-1",
title: "product 1",
},
},
])
})
})
describe("relation: options", () => {
let products: Product[]
let variants: ProductVariant[]
let options: ProductOption[]
beforeEach(async () => {
const testManager = await MikroOrmWrapper.forkManager()
products = (await createProductAndTags(
testManager,
productsData
)) as Product[]
variants = (await createProductVariants(
testManager,
variantsData
)) as ProductVariant[]
options = await createOptions(testManager, [
{
id: "test-option-1",
title: "size",
product: products[0],
values: [
{
id: "value-1",
value: "XS",
variant: products[0].variants[0],
},
{
id: "value-1",
value: "XL",
variant: products[0].variants[0],
},
],
},
{
id: "test-option-2",
title: "color",
product: products[0],
value: "blue",
variant: products[0].variants[0],
},
])
})
it("filter by options relation", async () => {
const variants = await service.list(
{ options: { id: ["value-1"] } },
{ relations: ["options"] }
)
expect(JSON.parse(JSON.stringify(variants))).toEqual([
expect.objectContaining({
id: productVariantTestOne,
title: "variant title",
sku: "sku 1",
}),
])
})
})
describe("create", function () {
let products: Product[]
let productOptions!: ProductOption[]
beforeEach(async () => {
const testManager = await MikroOrmWrapper.forkManager()
products = (await createProductAndTags(
testManager,
productsData
)) as Product[]
productOptions = await createOptions(testManager, [
{
id: "test-option-1",
title: "size",
product: products[0],
},
])
})
it("should create a variant", async () => {
const data = buildProductVariantOnlyData({
options: [
{
option: productOptions[0],
value: "XS",
},
],
})
const variants = await service.create(products[0].id, [data])
expect(variants).toHaveLength(1)
expect(variants[0].options).toHaveLength(1)
expect(JSON.parse(JSON.stringify(variants[0]))).toEqual(
expect.objectContaining({
id: expect.any(String),
title: data.title,
sku: data.sku,
allow_backorder: false,
manage_inventory: true,
variant_rank: 0,
product: expect.objectContaining({
id: products[0].id,
}),
options: expect.arrayContaining([
expect.objectContaining({
id: expect.any(String),
value: data.options![0].value,
}),
]),
})
)
})
})
describe("retrieve", () => {
beforeEach(async () => {
const testManager = await MikroOrmWrapper.forkManager()
productOne = testManager.create(Product, {
id: "product-1",
title: "product 1",
status: ProductStatus.PUBLISHED,
})
variantOne = testManager.create(ProductVariant, {
id: productVariantTestOne,
title: "variant 1",
product: productOne,
})
await testManager.persistAndFlush([variantOne])
})
it("should return the requested variant", async () => {
const result = await service.retrieve(variantOne.id)
expect(result).toEqual(
expect.objectContaining({
id: productVariantTestOne,
title: "variant 1",
})
)
})
it("should return requested attributes when requested through config", async () => {
const result = await service.retrieve(variantOne.id, {
select: ["id", "title", "product.title"] as any,
relations: ["product"],
})
expect(result).toEqual(
expect.objectContaining({
id: productVariantTestOne,
title: "variant 1",
product_id: "product-1",
product: expect.objectContaining({
id: "product-1",
title: "product 1",
}),
})
)
})
it("should throw an error when a variant with ID does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"ProductVariant with id: does-not-exist was not found"
)
})
it("should throw an error when an id is not provided", async () => {
let error
try {
await service.retrieve(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual("productVariant - id must be defined")
})
})
})
},
})

View File

@@ -22,6 +22,7 @@ import { ProductCategoryService, ProductService } from "@services"
import {
arrayDifference,
EmitEvents,
InjectManager,
InjectTransactionManager,
isPresent,
@@ -51,6 +52,7 @@ import {
UpdateTypeInput,
} from "../types"
import { entityNameToLinkableKeysMap, joinerConfig } from "./../joiner-config"
import { eventBuilders } from "../utils"
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
@@ -128,7 +130,6 @@ export default class ProductModuleService<
protected readonly productService_: ProductService<TProduct>
// eslint-disable-next-line max-len
protected readonly productVariantService_: ModulesSdkTypes.InternalModuleService<TProductVariant>
// eslint-disable-next-line max-len
protected readonly productCategoryService_: ProductCategoryService<TProductCategory>
// eslint-disable-next-line max-len
@@ -193,6 +194,7 @@ export default class ProductModuleService<
): Promise<ProductTypes.ProductVariantDTO>
@InjectManager("baseRepository_")
@EmitEvents()
async createVariants(
data:
| ProductTypes.CreateProductVariantDTO[]
@@ -220,7 +222,7 @@ export default class ProductModuleService<
if (data.some((v) => !v.product_id)) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"Tried to create variants without specifying a product_id"
"Unable to create variants without specifying a product_id"
)
}
@@ -238,10 +240,17 @@ export default class ProductModuleService<
const productVariantsWithOptions =
ProductModuleService.assignOptionsToVariants(data, productOptions)
return await this.productVariantService_.create(
const createdVariants = await this.productVariantService_.create(
productVariantsWithOptions,
sharedContext
)
eventBuilders.createdProductVariant({
data: createdVariants,
sharedContext,
})
return createdVariants
}
async upsertVariants(
@@ -254,6 +263,7 @@ export default class ProductModuleService<
): Promise<ProductTypes.ProductVariantDTO>
@InjectTransactionManager("baseRepository_")
@EmitEvents()
async upsertVariants(
data:
| ProductTypes.UpsertProductVariantDTO[]
@@ -300,6 +310,7 @@ export default class ProductModuleService<
): Promise<ProductTypes.ProductVariantDTO[]>
@InjectManager("baseRepository_")
@EmitEvents()
async updateVariants(
idOrSelector: string | ProductTypes.FilterableProductVariantProps,
data: ProductTypes.UpdateProductVariantDTO,
@@ -373,7 +384,7 @@ export default class ProductModuleService<
sharedContext
)
const { entities: productVariants } =
const { entities: productVariants, performedActions } =
await this.productVariantService_.upsertWithReplace(
ProductModuleService.assignOptionsToVariants(
variantsWithProductId,
@@ -385,6 +396,19 @@ export default class ProductModuleService<
sharedContext
)
eventBuilders.createdProductVariant({
data: performedActions.created[ProductVariant.name] ?? [],
sharedContext,
})
eventBuilders.updatedProductVariant({
data: performedActions.updated[ProductVariant.name] ?? [],
sharedContext,
})
eventBuilders.deletedProductVariant({
data: performedActions.deleted[ProductVariant.name] ?? [],
sharedContext,
})
return productVariants
}

View File

@@ -5,6 +5,8 @@ export type InitializeModuleInjectableDependencies = {
eventBusModuleService?: IEventBusModuleService
}
// TODO: remove and cleanup bellow code
export type ProductCategoryEventData = {
id: string
}

View File

@@ -0,0 +1,102 @@
import {
CommonEvents,
eventBuilderFactory,
Modules,
ProductEvents,
} from "@medusajs/utils"
export const eventBuilders = {
createdProduct: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.CREATED,
object: "product",
eventsEnum: ProductEvents,
isMainEntity: true,
}),
updatedProduct: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.UPDATED,
object: "product",
eventsEnum: ProductEvents,
isMainEntity: true,
}),
deletedProduct: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.DELETED,
object: "product",
eventsEnum: ProductEvents,
isMainEntity: true,
}),
createdProductVariant: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.CREATED,
object: "product_variant",
eventsEnum: ProductEvents,
}),
updatedProductVariant: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.UPDATED,
object: "product_variant",
eventsEnum: ProductEvents,
}),
deletedProductVariant: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.DELETED,
object: "product_variant",
eventsEnum: ProductEvents,
}),
createdProductOption: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.CREATED,
object: "product_option",
eventsEnum: ProductEvents,
}),
updatedProductOption: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.UPDATED,
object: "product_option",
eventsEnum: ProductEvents,
}),
deletedProductOption: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.DELETED,
object: "product_option",
eventsEnum: ProductEvents,
}),
createdProductType: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.CREATED,
object: "product_type",
eventsEnum: ProductEvents,
}),
updatedProductType: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.UPDATED,
object: "product_type",
eventsEnum: ProductEvents,
}),
deletedProductType: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.DELETED,
object: "product_type",
eventsEnum: ProductEvents,
}),
createdProductTag: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.CREATED,
object: "product_tag",
eventsEnum: ProductEvents,
}),
updatedProductTag: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.UPDATED,
object: "product_tag",
eventsEnum: ProductEvents,
}),
deletedProductTag: eventBuilderFactory({
service: Modules.PRODUCT,
action: CommonEvents.DELETED,
object: "product_tag",
eventsEnum: ProductEvents,
}),
}

View File

@@ -0,0 +1 @@
export * from "./events"