diff --git a/.changeset/tidy-gifts-talk.md b/.changeset/tidy-gifts-talk.md new file mode 100644 index 0000000000..552a937a45 --- /dev/null +++ b/.changeset/tidy-gifts-talk.md @@ -0,0 +1,7 @@ +--- +"@medusajs/core-flows": minor +"@medusajs/product": minor +"@medusajs/types": minor +--- + +Updated the signature of the product module variant and options endpoints to follow our conventions diff --git a/packages/core-flows/src/handlers/product/update-product-variants.ts b/packages/core-flows/src/handlers/product/update-product-variants.ts index 2ac0ff4a3a..7e0963d3c8 100644 --- a/packages/core-flows/src/handlers/product/update-product-variants.ts +++ b/packages/core-flows/src/handlers/product/update-product-variants.ts @@ -27,7 +27,7 @@ export async function updateProductVariants({ } if (updateVariantsData.length) { - await productModuleService.updateVariants(updateVariantsData) + await productModuleService.upsertVariants(updateVariantsData) } return productsVariants diff --git a/packages/core-flows/src/product/steps/update-product-options.ts b/packages/core-flows/src/product/steps/update-product-options.ts index c59a4ff099..d78ac578c2 100644 --- a/packages/core-flows/src/product/steps/update-product-options.ts +++ b/packages/core-flows/src/product/steps/update-product-options.ts @@ -25,9 +25,10 @@ export const updateProductOptionsStep = createStep( relations, }) - // TODO: We need to update the module's signature - // const productOptions = await service.updateOptions(data.selector, data.update) - const productOptions = [] + const productOptions = await service.updateOptions( + data.selector, + data.update + ) return new StepResponse(productOptions, prevData) }, async (prevData, { container }) => { @@ -39,11 +40,6 @@ export const updateProductOptionsStep = createStep( ModuleRegistrationName.PRODUCT ) - // TODO: We need to update the module's signature - // await service.upsertOptions( - // prevData.map((r) => ({ - // ...r, - // })) - // ) + await service.upsertOptions(prevData) } ) diff --git a/packages/core-flows/src/product/steps/update-product-variants.ts b/packages/core-flows/src/product/steps/update-product-variants.ts index 767b1e7e58..fdfab02fe6 100644 --- a/packages/core-flows/src/product/steps/update-product-variants.ts +++ b/packages/core-flows/src/product/steps/update-product-variants.ts @@ -25,9 +25,10 @@ export const updateProductVariantsStep = createStep( relations, }) - // TODO: We need to update the module's signature - // const productVariants = await service.updateVariants(data.selector, data.update) - const productVariants = [] + const productVariants = await service.updateVariants( + data.selector, + data.update + ) return new StepResponse(productVariants, prevData) }, async (prevData, { container }) => { @@ -39,11 +40,6 @@ export const updateProductVariantsStep = createStep( ModuleRegistrationName.PRODUCT ) - // TODO: We need to update the module's signature - // await service.upsertVariants( - // prevData.map((r) => ({ - // ...r, - // })) - // ) + await service.upsertVariants(prevData) } ) diff --git a/packages/product/integration-tests/__tests__/services/product-module-service/product-options.spec.ts b/packages/product/integration-tests/__tests__/services/product-module-service/product-options.spec.ts index 31780f9de1..e1e4f39df9 100644 --- a/packages/product/integration-tests/__tests__/services/product-module-service/product-options.spec.ts +++ b/packages/product/integration-tests/__tests__/services/product-module-service/product-options.spec.ts @@ -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", }, diff --git a/packages/product/src/services/product-module-service.ts b/packages/product/src/services/product-module-service.ts index f53ab94154..0be18dc29a 100644 --- a/packages/product/src/services/product-module-service.ts +++ b/packages/product/src/services/product-module-service.ts @@ -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 + createVariants( + data: ProductTypes.CreateProductVariantDTO, + sharedContext?: Context + ): Promise + + @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 { - const productVariantsWithOptions = await promiseAll( - data.map(async (variant) => { - if (!isPresent(variant.options)) { - return variant - } + ): Promise { + 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(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 + async upsertVariants( + data: ProductTypes.UpsertProductVariantDTO, + sharedContext?: Context + ): Promise + + @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 + updateVariants( + selector: ProductTypes.FilterableProductVariantProps, + data: ProductTypes.UpdateProductVariantDTO, + sharedContext?: Context + ): Promise + @InjectManager("baseRepository_") async updateVariants( - data: ProductTypes.UpdateProductVariantDTO[], + idOrSelector: string | ProductTypes.FilterableProductVariantProps, + data: ProductTypes.UpdateProductVariantDTO, @MedusaContext() sharedContext: Context = {} - ): Promise { - 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 { // 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 + createOptions( + data: ProductTypes.CreateProductOptionDTO, + sharedContext?: Context + ): Promise + + @InjectManager("baseRepository_") async createOptions( + data: + | ProductTypes.CreateProductOptionDTO[] + | ProductTypes.CreateProductOptionDTO, + @MedusaContext() sharedContext: Context = {} + ): Promise { + 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 { + 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 + async upsertOptions( + data: ProductTypes.UpsertProductOptionDTO, + sharedContext?: Context + ): Promise + + @InjectTransactionManager("baseRepository_") + async upsertOptions( + data: + | ProductTypes.UpsertProductOptionDTO[] + | ProductTypes.UpsertProductOptionDTO, + @MedusaContext() sharedContext: Context = {} + ): Promise { + 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 + updateOptions( + selector: ProductTypes.FilterableProductOptionProps, + data: ProductTypes.UpdateProductOptionDTO, + sharedContext?: Context + ): Promise + + @InjectManager("baseRepository_") + async updateOptions( + idOrSelector: string | ProductTypes.FilterableProductOptionProps, + data: ProductTypes.UpdateProductOptionDTO, + @MedusaContext() sharedContext: Context = {} + ): Promise { + 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 { + // 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 { diff --git a/packages/product/src/types/index.ts b/packages/product/src/types/index.ts index 9848404ace..1cb81ae2b2 100644 --- a/packages/product/src/types/index.ts +++ b/packages/product/src/types/index.ts @@ -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 } diff --git a/packages/types/src/product/common.ts b/packages/types/src/product/common.ts index 9a60ae1f48..7607b52ec5 100644 --- a/packages/types/src/product/common.ts +++ b/packages/types/src/product/common.ts @@ -1018,8 +1018,11 @@ export interface CreateProductOptionDTO { product_id?: string } +export interface UpsertProductOptionDTO extends UpdateProductOptionDTO { + id?: string +} + export interface UpdateProductOptionDTO { - id: string title?: string values?: string[] | { value: string }[] product_id?: string @@ -1109,8 +1112,7 @@ export interface CreateProductVariantDTO { metadata?: Record } -export interface UpsertProductVariantDTO - extends Omit { +export interface UpsertProductVariantDTO extends UpdateProductVariantDTO { /** * The ID of the product variant to update. */ @@ -1123,10 +1125,6 @@ export interface UpsertProductVariantDTO * The data to update in a product variant. The `id` is used to identify which product variant to update. */ export interface UpdateProductVariantDTO { - /** - * The ID of the product variant to update. - */ - id: string /** * The tile of the product variant. */ diff --git a/packages/types/src/product/service.ts b/packages/types/src/product/service.ts index 1f4270e14e..de559f1bfb 100644 --- a/packages/types/src/product/service.ts +++ b/packages/types/src/product/service.ts @@ -30,6 +30,8 @@ import { UpdateProductVariantDTO, UpsertProductCollectionDTO, UpsertProductDTO, + UpsertProductOptionDTO, + UpsertProductVariantDTO, } from "./common" import { FindConfig } from "../common" @@ -1256,25 +1258,25 @@ export interface IProductModuleService extends IModuleService { * * @param {CreateProductOptionDTO[]} data - The product options to be created. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. - * @returns {ProductOptionDTO[]} The list of created product options. + * @returns {Promise} The list of created product options. * * @example * import { * initialize as initializeProductModule, * } from "@medusajs/product" * - * async function createProductOption (title: string, productId: string) { + * async function createOptions (title: string) { * const productModule = await initializeProductModule() * - * const productOptions = await productModule.createOptions([ + * const options = await productModule.createOptions([ * { - * title, - * product_id: productId + * title * } * ]) * * // do something with the product options or return them * } + * */ createOptions( data: CreateProductOptionDTO[], @@ -1282,32 +1284,150 @@ export interface IProductModuleService extends IModuleService { ): Promise /** - * This method is used to update existing product options. + * This method is used to create a product option. * - * @param {UpdateProductOptionDTO[]} data - The product options to be updated, each holding the attributes that should be updated in the product option. + * @param {CreateProductOptionDTO} data - The product option to be created. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. - * @returns {ProductOptionDTO[]} The list of updated product options. + * @returns {Promise} The created product option. * * @example * import { * initialize as initializeProductModule, * } from "@medusajs/product" * - * async function updateProductOption (id: string, title: string) { + * async function createOption (title: string) { * const productModule = await initializeProductModule() * - * const productOptions = await productModule.updateOptions([ + * const option = await productModule.createOptions( + * { + * title + * } + * ) + * + * // do something with the product option or return them + * } + * + */ + createOptions( + data: CreateProductOptionDTO, + sharedContext?: Context + ): Promise + + /** + * This method updates existing options, or creates new ones if they don't exist. + * + * @param {UpsertProductOptionDTO[]} data - The attributes to update or create for each option. + * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. + * @returns {Promise} The updated and created options. + * + * @example + * import { + * initialize as initializeProductModule, + * } from "@medusajs/product" + * + * async function upsertOptions (title: string) { + * const productModule = await initializeProductModule() + * + * const createdOptions = await productModule.upsertOptions([ * { - * id, * title * } * ]) * - * // do something with the product options or return them + * // do something with the options or return them + * } + */ + upsertOptions( + data: UpsertProductOptionDTO[], + sharedContext?: Context + ): Promise + + /** + * This method updates an existing option, or creates a new one if it doesn't exist. + * + * @param {UpsertProductOptionDTO} data - The attributes to update or create for the option. + * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. + * @returns {Promise} The updated or created option. + * + * @example + * import { + * initialize as initializeProductModule, + * } from "@medusajs/product" + * + * async function upsertOption (title: string) { + * const productModule = await initializeProductModule() + * + * const createdOption = await productModule.upsertOptions( + * { + * title + * } + * ) + * + * // do something with the option or return it + * } + */ + upsertOptions( + data: UpsertProductOptionDTO, + sharedContext?: Context + ): Promise + + /** + * This method is used to update a option. + * + * @param {string} id - The ID of the option to be updated. + * @param {UpdateProductOptionDTO} data - The attributes of the option to be updated + * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. + * @returns {Promise} The updated option. + * + * @example + * import { + * initialize as initializeProductModule, + * } from "@medusajs/product" + * + * async function updateOption (id: string, title: string) { + * const productModule = await initializeProductModule() + * + * const option = await productModule.updateOptions(id, { + * title + * } + * ) + * + * // do something with the option or return it * } */ updateOptions( - data: UpdateProductOptionDTO[], + id: string, + data: UpdateProductOptionDTO, + sharedContext?: Context + ): Promise + + /** + * This method is used to update a list of options determined by the selector filters. + * + * @param {FilterableProductOptionProps} selector - The filters that will determine which options will be updated. + * @param {UpdateProductOptionDTO} data - The attributes to be updated on the selected options + * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. + * @returns {Promise} The updated options. + * + * @example + * import { + * initialize as initializeProductModule, + * } from "@medusajs/product" + * + * async function updateOptions(ids: string[], title: string) { + * const productModule = await initializeProductModule() + * + * const options = await productModule.updateOptions({id: ids}, { + * title + * } + * ) + * + * // do something with the options or return them + * } + */ + updateOptions( + selector: FilterableProductOptionProps, + data: UpdateProductOptionDTO, sharedContext?: Context ): Promise @@ -1560,58 +1680,180 @@ export interface IProductModuleService extends IModuleService { ): Promise /** - * This method is used to update a product's variants. + * This method is used to create product variants. * - * @param {UpdateProductVariantDTO[]} data - The product variants to update. + * @param {CreateProductVariantDTO[]} data - The product variants to be created. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. - * @returns {Promise} The updated product variants's details. + * @returns {Promise} The list of created product variants. * * @example * import { * initialize as initializeProductModule, * } from "@medusajs/product" - * import { - * UpdateProductVariantDTO - * } from "@medusajs/product/dist/types/services/product-variant" * - * async function updateProductVariants (items: UpdateProductVariantDTO[]) { + * async function createVariants (title: string) { * const productModule = await initializeProductModule() * - * const productVariants = await productModule.updateVariants(items) + * const variants = await productModule.createVariants([ + * { + * title + * } + * ]) * * // do something with the product variants or return them * } + * */ - updateVariants( - data: UpdateProductVariantDTO[], + createVariants( + data: CreateProductVariantDTO[], sharedContext?: Context ): Promise /** - * This method is used to create variants for a product. + * This method is used to create a product variant. * - * @param {CreateProductVariantDTO[]} data - The product variants to create. + * @param {CreateProductVariantDTO} data - The product variant to be created. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. - * @returns {Promise} The created product variants' details. + * @returns {Promise} The created product variant. * * @example * import { * initialize as initializeProductModule, * } from "@medusajs/product" * - * async function createProductVariants (items: { - * product_id: string, - * title: string - * }[]) { + * async function createVariant (title: string) { * const productModule = await initializeProductModule() * - * const productVariants = await productModule.createVariants(items) + * const variant = await productModule.createVariants( + * { + * title + * } + * ) * - * // do something with the product variants or return them + * // do something with the product variant or return them * } + * */ createVariants( - data: CreateProductVariantDTO[], + data: CreateProductVariantDTO, + sharedContext?: Context + ): Promise + + /** + * This method updates existing variants, or creates new ones if they don't exist. + * + * @param {UpsertProductVariantDTO[]} data - The attributes to update or create for each variant. + * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. + * @returns {Promise} The updated and created variants. + * + * @example + * import { + * initialize as initializeProductModule, + * } from "@medusajs/product" + * + * async function upsertVariants (title: string) { + * const productModule = await initializeProductModule() + * + * const createdVariants = await productModule.upsertVariants([ + * { + * title + * } + * ]) + * + * // do something with the variants or return them + * } + */ + upsertVariants( + data: UpsertProductVariantDTO[], + sharedContext?: Context + ): Promise + + /** + * This method updates an existing variant, or creates a new one if it doesn't exist. + * + * @param {UpsertProductVariantDTO} data - The attributes to update or create for the variant. + * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. + * @returns {Promise} The updated or created variant. + * + * @example + * import { + * initialize as initializeProductModule, + * } from "@medusajs/product" + * + * async function upsertVariant (title: string) { + * const productModule = await initializeProductModule() + * + * const createdVariant = await productModule.upsertVariants( + * { + * title + * } + * ) + * + * // do something with the variant or return it + * } + */ + upsertVariants( + data: UpsertProductVariantDTO, + sharedContext?: Context + ): Promise + + /** + * This method is used to update a variant. + * + * @param {string} id - The ID of the variant to be updated. + * @param {UpdateProductVariantDTO} data - The attributes of the variant to be updated + * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. + * @returns {Promise} The updated variant. + * + * @example + * import { + * initialize as initializeProductModule, + * } from "@medusajs/product" + * + * async function updateVariant (id: string, title: string) { + * const productModule = await initializeProductModule() + * + * const variant = await productModule.updateVariants(id, { + * title + * } + * ) + * + * // do something with the variant or return it + * } + */ + updateVariants( + id: string, + data: UpdateProductVariantDTO, + sharedContext?: Context + ): Promise + + /** + * This method is used to update a list of variants determined by the selector filters. + * + * @param {FilterableProductVariantProps} selector - The filters that will determine which variants will be updated. + * @param {UpdateProductVariantDTO} data - The attributes to be updated on the selected variants + * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. + * @returns {Promise} The updated variants. + * + * @example + * import { + * initialize as initializeProductModule, + * } from "@medusajs/product" + * + * async function updateVariants(ids: string[], title: string) { + * const productModule = await initializeProductModule() + * + * const variants = await productModule.updateVariants({id: ids}, { + * title + * } + * ) + * + * // do something with the variants or return them + * } + */ + updateVariants( + selector: FilterableProductVariantProps, + data: UpdateProductVariantDTO, sharedContext?: Context ): Promise @@ -2147,10 +2389,10 @@ export interface IProductModuleService extends IModuleService { * initialize as initializeProductModule, * } from "@medusajs/product" * - * async function upserCollections (title: string) { + * async function upsertCollections (title: string) { * const productModule = await initializeProductModule() * - * const createdCollections = await productModule.upsert([ + * const createdCollections = await productModule.upsertCollections([ * { * title * } @@ -2176,10 +2418,10 @@ export interface IProductModuleService extends IModuleService { * initialize as initializeProductModule, * } from "@medusajs/product" * - * async function upserCollection (title: string) { + * async function upsertCollection (title: string) { * const productModule = await initializeProductModule() * - * const createdCollection = await productModule.upsert( + * const createdCollection = await productModule.upsertCollection( * { * title * }