feat: Update the signatures for variants and options to follow convention (#6748)

This commit is contained in:
Stevche Radevski authored and GitHub committed 2024-03-20 11:31:54 +00:00
1 parent a859b7895e
commit 05e857d256
9 files changed
+574 -117

No files matched your search

@@ -242,7 +242,7 @@ moduleIntegrationTestRunner({
const optionId = "option-1"
it("should update the title of the option successfully", async () => {
await service.updateOptions([
await service.upsertOptions([
{
id: optionId,
title: "new test",
@@ -258,7 +258,7 @@ moduleIntegrationTestRunner({
let error
try {
await service.updateOptions([
await service.upsertOptions([
{
id: "does-not-exist",
},
@@ -32,7 +32,6 @@ import {
arrayDifference,
InjectManager,
InjectTransactionManager,
isPresent,
isString,
kebabCase,
MedusaContext,
@@ -50,6 +49,7 @@ import {
ProductCollectionEventData,
ProductCollectionEvents,
UpdateProductVariantInput,
UpdateProductOptionInput,
} from "../types"
import { entityNameToLinkableKeysMap, joinerConfig } from "./../joiner-config"
import { ProductStatus } from "@medusajs/utils"
@@ -197,58 +197,158 @@ export default class ProductModuleService<
return joinerConfig
}
// TODO: Add options validation, among other things
createVariants(
data: ProductTypes.CreateProductVariantDTO[],
sharedContext?: Context
): Promise<ProductTypes.ProductVariantDTO[]>
createVariants(
data: ProductTypes.CreateProductVariantDTO,
sharedContext?: Context
): Promise<ProductTypes.ProductVariantDTO>
@InjectManager("baseRepository_")
async createVariants(
data:
| ProductTypes.CreateProductVariantDTO[]
| ProductTypes.CreateProductVariantDTO,
@MedusaContext() sharedContext: Context = {}
): Promise<
ProductTypes.ProductVariantDTO[] | ProductTypes.ProductVariantDTO
> {
const input = Array.isArray(data) ? data : [data]
const variants = await this.createVariants_(input, sharedContext)
const createdVariants = await this.baseRepository_.serialize<
ProductTypes.ProductVariantDTO[]
>(variants, { populate: true })
return Array.isArray(data) ? createdVariants : createdVariants[0]
}
@InjectTransactionManager("baseRepository_")
protected async createVariants_(
data: ProductTypes.CreateProductVariantDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<ProductTypes.ProductVariantDTO[]> {
const productVariantsWithOptions = await promiseAll(
data.map(async (variant) => {
if (!isPresent(variant.options)) {
return variant
}
): Promise<ProductVariant[]> {
if (data.some((v) => !v.product_id)) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"Tried to create variants without specifying a product_id"
)
}
const productOptions = await this.productOptionService_.list(
{ product_id: variant.product_id },
{
take: null,
},
sharedContext
)
return ProductModuleService.assignOptionsToVariants(
[variant],
productOptions
)[0]
})
)
const productVariants = await this.productVariantService_.create(
productVariantsWithOptions,
const productOptions = await this.productOptionService_.list(
{
product_id: [...new Set<string>(data.map((v) => v.product_id!))],
},
{
take: null,
},
sharedContext
)
return await this.baseRepository_.serialize<
ProductTypes.ProductVariantDTO[]
>(productVariants)
const productVariantsWithOptions =
ProductModuleService.assignOptionsToVariants(data, productOptions)
return await this.productVariantService_.create(
productVariantsWithOptions,
sharedContext
)
}
async upsertVariants(
data: ProductTypes.UpsertProductVariantDTO[],
sharedContext?: Context
): Promise<ProductTypes.ProductVariantDTO[]>
async upsertVariants(
data: ProductTypes.UpsertProductVariantDTO,
sharedContext?: Context
): Promise<ProductTypes.ProductVariantDTO>
@InjectTransactionManager("baseRepository_")
async upsertVariants(
data:
| ProductTypes.UpsertProductVariantDTO[]
| ProductTypes.UpsertProductVariantDTO,
@MedusaContext() sharedContext: Context = {}
): Promise<
ProductTypes.ProductVariantDTO[] | ProductTypes.ProductVariantDTO
> {
const input = Array.isArray(data) ? data : [data]
const forUpdate = input.filter(
(variant): variant is UpdateProductVariantInput => !!variant.id
)
const forCreate = input.filter(
(variant): variant is ProductTypes.CreateProductVariantDTO => !variant.id
)
let created: ProductVariant[] = []
let updated: ProductVariant[] = []
if (forCreate.length) {
created = await this.createVariants_(forCreate, sharedContext)
}
if (forUpdate.length) {
updated = await this.updateVariants_(forUpdate, sharedContext)
}
const result = [...created, ...updated]
const allVariants = await this.baseRepository_.serialize<
ProductTypes.ProductVariantDTO[] | ProductTypes.ProductVariantDTO
>(result)
return Array.isArray(data) ? allVariants : allVariants[0]
}
updateVariants(
id: string,
data: ProductTypes.UpdateProductVariantDTO,
sharedContext?: Context
): Promise<ProductTypes.ProductVariantDTO>
updateVariants(
selector: ProductTypes.FilterableProductVariantProps,
data: ProductTypes.UpdateProductVariantDTO,
sharedContext?: Context
): Promise<ProductTypes.ProductVariantDTO[]>
@InjectManager("baseRepository_")
async updateVariants(
data: ProductTypes.UpdateProductVariantDTO[],
idOrSelector: string | ProductTypes.FilterableProductVariantProps,
data: ProductTypes.UpdateProductVariantDTO,
@MedusaContext() sharedContext: Context = {}
): Promise<ProductTypes.ProductVariantDTO[]> {
const productVariants = await this.updateVariants_(data, sharedContext)
): Promise<
ProductTypes.ProductVariantDTO[] | ProductTypes.ProductVariantDTO
> {
let normalizedInput: UpdateProductVariantInput[] = []
if (isString(idOrSelector)) {
normalizedInput = [{ id: idOrSelector, ...data }]
} else {
const variants = await this.productVariantService_.list(
idOrSelector,
{},
sharedContext
)
normalizedInput = variants.map((variant) => ({
id: variant.id,
...data,
}))
}
const variants = await this.updateVariants_(normalizedInput, sharedContext)
const updatedVariants = await this.baseRepository_.serialize<
ProductTypes.ProductVariantDTO[]
>(productVariants)
>(variants)
return updatedVariants
return isString(idOrSelector) ? updatedVariants[0] : updatedVariants
}
@InjectTransactionManager("baseRepository_")
protected async updateVariants_(
data: ProductTypes.UpdateProductVariantDTO[],
data: UpdateProductVariantInput[],
@MedusaContext() sharedContext: Context = {}
): Promise<TProductVariant[]> {
// Validation step
@@ -280,7 +380,7 @@ export default class ProductModuleService<
const productOptions = await this.productOptionService_.list(
{
product_id: Array.from(
new Set(variantsWithProductId.map((v) => v.product_id))
new Set(variantsWithProductId.map((v) => v.product_id!))
),
},
{ take: null },
@@ -294,8 +394,8 @@ export default class ProductModuleService<
)
}
@InjectManager("baseRepository_")
async diffVariants_(
@InjectTransactionManager("baseRepository_")
protected async diffVariants_(
data: UpdateProductVariantInput[],
productOptions: ProductOption[],
@MedusaContext() sharedContext: Context = {}
@@ -427,11 +527,45 @@ export default class ProductModuleService<
})
}
@InjectTransactionManager("baseRepository_")
createOptions(
data: ProductTypes.CreateProductOptionDTO[],
sharedContext?: Context
): Promise<ProductTypes.ProductOptionDTO[]>
createOptions(
data: ProductTypes.CreateProductOptionDTO,
sharedContext?: Context
): Promise<ProductTypes.ProductOptionDTO>
@InjectManager("baseRepository_")
async createOptions(
data:
| ProductTypes.CreateProductOptionDTO[]
| ProductTypes.CreateProductOptionDTO,
@MedusaContext() sharedContext: Context = {}
): Promise<ProductTypes.ProductOptionDTO[] | ProductTypes.ProductOptionDTO> {
const input = Array.isArray(data) ? data : [data]
const options = await this.createOptions_(input, sharedContext)
const createdOptions = await this.baseRepository_.serialize<
ProductTypes.ProductOptionDTO[]
>(options, { populate: true })
return Array.isArray(data) ? createdOptions : createdOptions[0]
}
@InjectTransactionManager("baseRepository_")
protected async createOptions_(
data: ProductTypes.CreateProductOptionDTO[],
@MedusaContext() sharedContext: Context = {}
) {
): Promise<ProductOption[]> {
if (data.some((v) => !v.product_id)) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"Tried to create options without specifying a product_id"
)
}
const normalizedInput = data.map((opt) => {
return {
...opt,
@@ -441,21 +575,102 @@ export default class ProductModuleService<
}
})
const productOptions = await this.productOptionService_.create(
return await this.productOptionService_.create(
normalizedInput,
sharedContext
)
}
return await this.baseRepository_.serialize<
async upsertOptions(
data: ProductTypes.UpsertProductOptionDTO[],
sharedContext?: Context
): Promise<ProductTypes.ProductOptionDTO[]>
async upsertOptions(
data: ProductTypes.UpsertProductOptionDTO,
sharedContext?: Context
): Promise<ProductTypes.ProductOptionDTO>
@InjectTransactionManager("baseRepository_")
async upsertOptions(
data:
| ProductTypes.UpsertProductOptionDTO[]
| ProductTypes.UpsertProductOptionDTO,
@MedusaContext() sharedContext: Context = {}
): Promise<ProductTypes.ProductOptionDTO[] | ProductTypes.ProductOptionDTO> {
const input = Array.isArray(data) ? data : [data]
const forUpdate = input.filter(
(option): option is UpdateProductOptionInput => !!option.id
)
const forCreate = input.filter(
(option): option is ProductTypes.CreateProductOptionDTO => !option.id
)
let created: ProductOption[] = []
let updated: ProductOption[] = []
if (forCreate.length) {
created = await this.createOptions_(forCreate, sharedContext)
}
if (forUpdate.length) {
updated = await this.updateOptions_(forUpdate, sharedContext)
}
const result = [...created, ...updated]
const allOptions = await this.baseRepository_.serialize<
ProductTypes.ProductOptionDTO[] | ProductTypes.ProductOptionDTO
>(result)
return Array.isArray(data) ? allOptions : allOptions[0]
}
updateOptions(
id: string,
data: ProductTypes.UpdateProductOptionDTO,
sharedContext?: Context
): Promise<ProductTypes.ProductOptionDTO>
updateOptions(
selector: ProductTypes.FilterableProductOptionProps,
data: ProductTypes.UpdateProductOptionDTO,
sharedContext?: Context
): Promise<ProductTypes.ProductOptionDTO[]>
@InjectManager("baseRepository_")
async updateOptions(
idOrSelector: string | ProductTypes.FilterableProductOptionProps,
data: ProductTypes.UpdateProductOptionDTO,
@MedusaContext() sharedContext: Context = {}
): Promise<ProductTypes.ProductOptionDTO[] | ProductTypes.ProductOptionDTO> {
let normalizedInput: UpdateProductOptionInput[] = []
if (isString(idOrSelector)) {
normalizedInput = [{ id: idOrSelector, ...data }]
} else {
const options = await this.productOptionService_.list(
idOrSelector,
{},
sharedContext
)
normalizedInput = options.map((option) => ({
id: option.id,
...data,
}))
}
const options = await this.updateOptions_(normalizedInput, sharedContext)
const updatedOptions = await this.baseRepository_.serialize<
ProductTypes.ProductOptionDTO[]
>(productOptions)
>(options)
return isString(idOrSelector) ? updatedOptions[0] : updatedOptions
}
@InjectTransactionManager("baseRepository_")
async updateOptions(
data: ProductTypes.UpdateProductOptionDTO[],
protected async updateOptions_(
data: UpdateProductOptionInput[],
@MedusaContext() sharedContext: Context = {}
) {
): Promise<ProductOption[]> {
// Validation step
const normalizedInput = data.map((opt) => {
return {
...opt,
@@ -466,7 +681,7 @@ export default class ProductModuleService<
}),
}
: {}),
} as ProductTypes.UpdateProductOptionDTO
} as UpdateProductOptionInput
})
if (normalizedInput.some((option) => !option.id)) {
@@ -481,15 +696,13 @@ export default class ProductModuleService<
sharedContext
)
return await this.baseRepository_.serialize<
ProductTypes.ProductOptionDTO[]
>(productOptions)
return productOptions
}
// TODO: Do validation
@InjectTransactionManager("baseRepository_")
async diffOptions_(
data: ProductTypes.UpdateProductOptionDTO[],
protected async diffOptions_(
data: UpdateProductOptionInput[],
@MedusaContext() sharedContext: Context = {}
) {
const toCreate = data.filter((o) => !o.id)
@@ -740,7 +953,7 @@ export default class ProductModuleService<
}
@InjectTransactionManager("baseRepository_")
async updateCollections_(
protected async updateCollections_(
data: UpdateCollectionInput[],
@MedusaContext() sharedContext: Context = {}
): Promise<TProductCollection[]> {
+6 -1
View File
@@ -54,5 +54,10 @@ export type UpdateCollectionInput = ProductTypes.UpdateProductCollectionDTO & {
}
export type UpdateProductVariantInput = ProductTypes.UpdateProductVariantDTO & {
product_id: string
id: string
product_id?: string
}
export type UpdateProductOptionInput = ProductTypes.UpdateProductOptionDTO & {
id: string
}