@medusajs/product 3.0.0-snapshot-20251106181920 → 3.0.0-snapshot-20251126221441
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/migrations/Migration20250911092221.d.ts +1 -1
- package/dist/migrations/Migration20250911092221.d.ts.map +1 -1
- package/dist/migrations/Migration20250911092221.js +1 -1
- package/dist/migrations/Migration20250911092221.js.map +1 -1
- package/dist/migrations/Migration20251011090511.d.ts +1 -1
- package/dist/migrations/Migration20251011090511.d.ts.map +1 -1
- package/dist/migrations/Migration20251011090511.js +1 -1
- package/dist/migrations/Migration20251011090511.js.map +1 -1
- package/dist/models/index.d.ts +0 -1
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +1 -3
- package/dist/models/index.js.map +1 -1
- package/dist/models/product-category.d.ts +6 -14
- package/dist/models/product-category.d.ts.map +1 -1
- package/dist/models/product-collection.d.ts +6 -14
- package/dist/models/product-collection.d.ts.map +1 -1
- package/dist/models/product-image.d.ts +14 -26
- package/dist/models/product-image.d.ts.map +1 -1
- package/dist/models/product-option-value.d.ts +12 -18
- package/dist/models/product-option-value.d.ts.map +1 -1
- package/dist/models/product-option-value.js +0 -1
- package/dist/models/product-option-value.js.map +1 -1
- package/dist/models/product-option.d.ts +6 -10
- package/dist/models/product-option.d.ts.map +1 -1
- package/dist/models/product-option.js +12 -4
- package/dist/models/product-option.js.map +1 -1
- package/dist/models/product-tag.d.ts +6 -14
- package/dist/models/product-tag.d.ts.map +1 -1
- package/dist/models/product-type.d.ts +6 -14
- package/dist/models/product-type.d.ts.map +1 -1
- package/dist/models/product-variant-product-image.d.ts +26 -47
- package/dist/models/product-variant-product-image.d.ts.map +1 -1
- package/dist/models/product-variant.d.ts +12 -21
- package/dist/models/product-variant.d.ts.map +1 -1
- package/dist/models/product.d.ts +6 -14
- package/dist/models/product.d.ts.map +1 -1
- package/dist/models/product.js +3 -5
- package/dist/models/product.js.map +1 -1
- package/dist/repositories/product-category.d.ts +18 -36
- package/dist/repositories/product-category.d.ts.map +1 -1
- package/dist/repositories/product.d.ts +6 -14
- package/dist/repositories/product.d.ts.map +1 -1
- package/dist/repositories/product.js +5 -2
- package/dist/repositories/product.js.map +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -0
- package/dist/schema/index.js.map +1 -1
- package/dist/services/product-module-service.d.ts +4 -20
- package/dist/services/product-module-service.d.ts.map +1 -1
- package/dist/services/product-module-service.js +90 -312
- package/dist/services/product-module-service.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/dist/migrations/Migration20251022153442.d.ts +0 -6
- package/dist/migrations/Migration20251022153442.d.ts.map +0 -1
- package/dist/migrations/Migration20251022153442.js +0 -104
- package/dist/migrations/Migration20251022153442.js.map +0 -1
- package/dist/migrations/Migration20251029150809.d.ts +0 -6
- package/dist/migrations/Migration20251029150809.d.ts.map +0 -1
- package/dist/migrations/Migration20251029150809.js +0 -14
- package/dist/migrations/Migration20251029150809.js.map +0 -1
- package/dist/models/product-product-option.d.ts +0 -668
- package/dist/models/product-product-option.d.ts.map +0 -1
- package/dist/models/product-product-option.js +0 -19
- package/dist/models/product-product-option.js.map +0 -1
|
@@ -11,7 +11,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
12
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
13
|
};
|
|
14
|
-
var _a
|
|
14
|
+
var _a;
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
const types_1 = require("@medusajs/framework/types");
|
|
17
17
|
const _models_1 = require("../models");
|
|
@@ -29,7 +29,7 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
29
29
|
ProductVariant: _models_1.ProductVariant,
|
|
30
30
|
ProductImage: _models_1.ProductImage,
|
|
31
31
|
}) {
|
|
32
|
-
constructor({ baseRepository, productRepository, productService, productVariantService, productTagService, productCategoryService, productCollectionService, productImageService, productTypeService, productOptionService,
|
|
32
|
+
constructor({ baseRepository, productRepository, productService, productVariantService, productTagService, productCategoryService, productCollectionService, productImageService, productTypeService, productOptionService, productOptionValueService, productVariantProductImageService, [utils_1.Modules.EVENT_BUS]: eventBusModuleService, }, moduleDeclaration) {
|
|
33
33
|
// @ts-ignore
|
|
34
34
|
// eslint-disable-next-line prefer-rest-params
|
|
35
35
|
super(...arguments);
|
|
@@ -44,7 +44,6 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
44
44
|
this.productImageService_ = productImageService;
|
|
45
45
|
this.productTypeService_ = productTypeService;
|
|
46
46
|
this.productOptionService_ = productOptionService;
|
|
47
|
-
this.productProductOptionService_ = productProductOptionService;
|
|
48
47
|
this.productOptionValueService_ = productOptionValueService;
|
|
49
48
|
this.productVariantProductImageService_ = productVariantProductImageService;
|
|
50
49
|
this.eventBusModuleService_ = eventBusModuleService;
|
|
@@ -143,11 +142,9 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
143
142
|
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Unable to create variants without specifying a product_id");
|
|
144
143
|
}
|
|
145
144
|
const productOptions = await this.productOptionService_.list({
|
|
146
|
-
|
|
147
|
-
id: [...new Set(data.map((v) => v.product_id))],
|
|
148
|
-
},
|
|
145
|
+
product_id: [...new Set(data.map((v) => v.product_id))],
|
|
149
146
|
}, {
|
|
150
|
-
relations: ["values"
|
|
147
|
+
relations: ["values"],
|
|
151
148
|
}, sharedContext);
|
|
152
149
|
const variants = await this.productVariantService_.list({
|
|
153
150
|
product_id: [...new Set(data.map((v) => v.product_id))],
|
|
@@ -207,10 +204,8 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
207
204
|
product_id: v.product_id,
|
|
208
205
|
}));
|
|
209
206
|
const productOptions = await this.productOptionService_.list({
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
},
|
|
213
|
-
}, { relations: ["values", "products"] }, sharedContext);
|
|
207
|
+
product_id: Array.from(new Set(variantsWithProductId.map((v) => v.product_id))),
|
|
208
|
+
}, { relations: ["values"] }, sharedContext);
|
|
214
209
|
const productVariantsWithOptions = ProductModuleService.assignOptionsToVariants(variantsWithProductId, productOptions);
|
|
215
210
|
if (data.some((d) => !!d.options)) {
|
|
216
211
|
ProductModuleService.checkIfVariantWithOptionsAlreadyExists(productVariantsWithOptions, allVariants);
|
|
@@ -318,25 +313,18 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
318
313
|
return Array.isArray(data) ? createdOptions : createdOptions[0];
|
|
319
314
|
}
|
|
320
315
|
async createOptions_(data, sharedContext = {}) {
|
|
316
|
+
if (data.some((v) => !v.product_id)) {
|
|
317
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Tried to create options without specifying a product_id");
|
|
318
|
+
}
|
|
321
319
|
const normalizedInput = data.map((opt) => {
|
|
322
|
-
Object.keys(opt.ranks ?? []).forEach((value) => {
|
|
323
|
-
if (!opt.values.includes(value)) {
|
|
324
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Value "${value}" is assigned a rank but is not defined in the list of values.`);
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
320
|
return {
|
|
328
321
|
...opt,
|
|
329
322
|
values: opt.values?.map((v) => {
|
|
330
|
-
|
|
331
|
-
const valueObj = (0, utils_1.isString)(v) ? { value: v } : v;
|
|
332
|
-
const rank = opt.ranks && (0, utils_1.isString)(v)
|
|
333
|
-
? opt.ranks[v]
|
|
334
|
-
: opt.ranks?.[valueObj.value];
|
|
335
|
-
return rank !== undefined ? { ...valueObj, rank } : valueObj;
|
|
323
|
+
return typeof v === "string" ? { value: v } : v;
|
|
336
324
|
}),
|
|
337
325
|
};
|
|
338
326
|
});
|
|
339
|
-
return this.productOptionService_.create(normalizedInput, sharedContext);
|
|
327
|
+
return await this.productOptionService_.create(normalizedInput, sharedContext);
|
|
340
328
|
}
|
|
341
329
|
async upsertProductOptions(data, sharedContext = {}) {
|
|
342
330
|
const input = Array.isArray(data) ? data : [data];
|
|
@@ -383,77 +371,35 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
383
371
|
}
|
|
384
372
|
// Data normalization
|
|
385
373
|
const normalizedInput = data.map((opt) => {
|
|
386
|
-
const
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
Object.keys(opt.ranks).forEach((value) => {
|
|
391
|
-
if (!validValues.includes(value)) {
|
|
392
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Value "${value}" is assigned a rank but is not defined in the list of values.`);
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
let normalizedValues;
|
|
397
|
-
if (opt.values) {
|
|
398
|
-
// If new values are provided → normalize and apply ranks
|
|
399
|
-
normalizedValues = opt.values.map((v) => {
|
|
400
|
-
const valueObj = (0, utils_1.isString)(v) ? { value: v } : v;
|
|
401
|
-
const rank = opt.ranks && (0, utils_1.isString)(v)
|
|
402
|
-
? opt.ranks[v]
|
|
403
|
-
: opt.ranks?.[valueObj.value];
|
|
404
|
-
const rankedValue = rank !== undefined ? { ...valueObj, rank } : valueObj;
|
|
405
|
-
if ("id" in rankedValue) {
|
|
406
|
-
return rankedValue;
|
|
407
|
-
}
|
|
408
|
-
const dbVal = dbValues.find((dbVal) => dbVal.value === rankedValue.value);
|
|
409
|
-
if (!dbVal) {
|
|
410
|
-
return rankedValue;
|
|
411
|
-
}
|
|
412
|
-
return {
|
|
413
|
-
id: dbVal.id,
|
|
414
|
-
...rankedValue,
|
|
415
|
-
};
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
else if (opt.ranks) {
|
|
419
|
-
// If only ranks were provided → update existing DB values with ranks
|
|
420
|
-
normalizedValues = dbValues.map((dbVal) => {
|
|
421
|
-
const rank = opt.ranks[dbVal.value];
|
|
422
|
-
return rank !== undefined
|
|
423
|
-
? { id: dbVal.id, value: dbVal.value, rank }
|
|
424
|
-
: { id: dbVal.id, value: dbVal.value };
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
const { ranks, ...cleanOpt } = opt;
|
|
374
|
+
const dbValues = dbOptions.find(({ id }) => id === opt.id)?.values || [];
|
|
375
|
+
const normalizedValues = opt.values?.map((v) => {
|
|
376
|
+
return typeof v === "string" ? { value: v } : v;
|
|
377
|
+
});
|
|
428
378
|
return {
|
|
429
|
-
...
|
|
430
|
-
...(normalizedValues
|
|
379
|
+
...opt,
|
|
380
|
+
...(normalizedValues
|
|
381
|
+
? {
|
|
382
|
+
// Oftentimes the options are only passed by value without an id, even if they exist in the DB
|
|
383
|
+
values: normalizedValues.map((normVal) => {
|
|
384
|
+
if ("id" in normVal) {
|
|
385
|
+
return normVal;
|
|
386
|
+
}
|
|
387
|
+
const dbVal = dbValues.find((dbVal) => dbVal.value === normVal.value);
|
|
388
|
+
if (!dbVal) {
|
|
389
|
+
return normVal;
|
|
390
|
+
}
|
|
391
|
+
return {
|
|
392
|
+
id: dbVal.id,
|
|
393
|
+
value: normVal.value,
|
|
394
|
+
};
|
|
395
|
+
}),
|
|
396
|
+
}
|
|
397
|
+
: {}),
|
|
431
398
|
};
|
|
432
399
|
});
|
|
433
400
|
const { entities: productOptions } = await this.productOptionService_.upsertWithReplace(normalizedInput, { relations: ["values"] }, sharedContext);
|
|
434
401
|
return productOptions;
|
|
435
402
|
}
|
|
436
|
-
async addProductOptionToProduct(data, sharedContext = {}) {
|
|
437
|
-
const productOptionProducts = await this.addProductOptionToProduct_(data, sharedContext);
|
|
438
|
-
return productOptionProducts;
|
|
439
|
-
}
|
|
440
|
-
async addProductOptionToProduct_(data, sharedContext = {}) {
|
|
441
|
-
const productOptionProducts = await this.productProductOptionService_.create(data, sharedContext);
|
|
442
|
-
if (Array.isArray(data)) {
|
|
443
|
-
return productOptionProducts.map((ppo) => ({ id: ppo.id }));
|
|
444
|
-
}
|
|
445
|
-
return { id: productOptionProducts.id };
|
|
446
|
-
}
|
|
447
|
-
async removeProductOptionFromProduct(data, sharedContext = {}) {
|
|
448
|
-
await this.removeProductOptionFromProduct_(data, sharedContext);
|
|
449
|
-
}
|
|
450
|
-
async removeProductOptionFromProduct_(data, sharedContext = {}) {
|
|
451
|
-
const pairs = Array.isArray(data) ? data : [data];
|
|
452
|
-
const productOptionsProducts = await this.productProductOptionService_.list({
|
|
453
|
-
$or: pairs,
|
|
454
|
-
});
|
|
455
|
-
await this.productProductOptionService_.delete(productOptionsProducts.map(({ id }) => id), sharedContext);
|
|
456
|
-
}
|
|
457
403
|
// @ts-expect-error
|
|
458
404
|
async createProductCollections(data, sharedContext = {}) {
|
|
459
405
|
const input = Array.isArray(data) ? data : [data];
|
|
@@ -678,40 +624,7 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
678
624
|
return (0, utils_1.isString)(idOrSelector) ? updatedProducts[0] : updatedProducts;
|
|
679
625
|
}
|
|
680
626
|
async createProducts_(data, sharedContext = {}) {
|
|
681
|
-
const
|
|
682
|
-
.flatMap((p) => p.options ?? [])
|
|
683
|
-
.filter((o) => "id" in o)
|
|
684
|
-
.map((o) => o.id);
|
|
685
|
-
let existingOptions = [];
|
|
686
|
-
if (existingOptionIds.length > 0) {
|
|
687
|
-
existingOptions = await this.productOptionService_.list({ id: existingOptionIds }, { relations: ["values"] }, sharedContext);
|
|
688
|
-
const fetchedIds = new Set(existingOptions.map((opt) => opt.id));
|
|
689
|
-
const missingIds = existingOptionIds.filter((id) => !fetchedIds.has(id));
|
|
690
|
-
if (missingIds.length) {
|
|
691
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Some product options were not found: [${missingIds.join(", ")}]`);
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
const existingOptionsMap = new Map(existingOptions.map((opt) => [opt.id, opt]));
|
|
695
|
-
const hydratedData = data.map((product) => {
|
|
696
|
-
if (!product.options?.length)
|
|
697
|
-
return product;
|
|
698
|
-
const hydratedOptions = product.options.map((option) => {
|
|
699
|
-
if ("id" in option) {
|
|
700
|
-
const dbOption = existingOptionsMap.get(option.id);
|
|
701
|
-
if (!dbOption) {
|
|
702
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Product option with id ${option.id} not found.`);
|
|
703
|
-
}
|
|
704
|
-
return {
|
|
705
|
-
id: dbOption.id,
|
|
706
|
-
title: dbOption.title,
|
|
707
|
-
values: dbOption.values?.map((v) => ({ value: v.value })),
|
|
708
|
-
};
|
|
709
|
-
}
|
|
710
|
-
return option;
|
|
711
|
-
});
|
|
712
|
-
return { ...product, options: hydratedOptions };
|
|
713
|
-
});
|
|
714
|
-
const normalizedProducts = this.normalizeCreateProductInput(hydratedData, sharedContext);
|
|
627
|
+
const normalizedProducts = await this.normalizeCreateProductInput(data, sharedContext);
|
|
715
628
|
for (const product of normalizedProducts) {
|
|
716
629
|
this.validateProductCreatePayload(product);
|
|
717
630
|
}
|
|
@@ -725,7 +638,6 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
725
638
|
}, {}, sharedContext);
|
|
726
639
|
}
|
|
727
640
|
const existingTagsMap = new Map(existingTags.map((tag) => [tag.id, tag]));
|
|
728
|
-
const productOptionsToCreate = new Map();
|
|
729
641
|
const productsToCreate = normalizedProducts.map((product) => {
|
|
730
642
|
const productId = (0, utils_1.generateEntityId)(product.id, "prod");
|
|
731
643
|
product.id = productId;
|
|
@@ -733,12 +645,6 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
733
645
|
;
|
|
734
646
|
product.categories = product.categories.map((category) => category.id);
|
|
735
647
|
}
|
|
736
|
-
if (product.options?.length) {
|
|
737
|
-
const newOptions = product.options.filter((o) => !("id" in o));
|
|
738
|
-
if (newOptions.length) {
|
|
739
|
-
productOptionsToCreate.set(productId, newOptions);
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
648
|
if (product.variants?.length) {
|
|
743
649
|
const normalizedVariants = product.variants.map((variant) => {
|
|
744
650
|
const variantId = (0, utils_1.generateEntityId)(variant.id, "variant");
|
|
@@ -764,66 +670,10 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
764
670
|
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Tag with id ${tag.id} not found. Please create the tag before associating it with the product.`);
|
|
765
671
|
});
|
|
766
672
|
}
|
|
767
|
-
delete product.options;
|
|
768
673
|
return product;
|
|
769
674
|
});
|
|
770
|
-
const
|
|
771
|
-
|
|
772
|
-
for (const [productId, options] of productOptionsToCreate.entries()) {
|
|
773
|
-
const optionIds = [];
|
|
774
|
-
for (const option of options) {
|
|
775
|
-
const optionId = (0, utils_1.generateEntityId)(undefined, "opt");
|
|
776
|
-
optionIds.push(optionId);
|
|
777
|
-
allOptionsWithIds.push({
|
|
778
|
-
...option,
|
|
779
|
-
id: optionId,
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
|
-
productToOptionIdsMap.set(productId, optionIds);
|
|
783
|
-
}
|
|
784
|
-
const [createdProducts] = await Promise.all([
|
|
785
|
-
this.productService_.create(productsToCreate, sharedContext),
|
|
786
|
-
allOptionsWithIds.length > 0
|
|
787
|
-
? this.createOptions_(allOptionsWithIds, sharedContext)
|
|
788
|
-
: Promise.resolve([]),
|
|
789
|
-
]);
|
|
790
|
-
const linkPairs = [];
|
|
791
|
-
for (const product of createdProducts) {
|
|
792
|
-
const hydratedProduct = hydratedData.find((p) => p.title === product.title);
|
|
793
|
-
const allOptionIds = [];
|
|
794
|
-
if (hydratedProduct?.options?.length) {
|
|
795
|
-
for (const option of hydratedProduct.options) {
|
|
796
|
-
if ("id" in option) {
|
|
797
|
-
allOptionIds.push(option.id);
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
const newOptionIds = productToOptionIdsMap.get(product.id) ?? [];
|
|
802
|
-
const optionIds = [...new Set([...allOptionIds, ...newOptionIds])];
|
|
803
|
-
for (const optionId of optionIds) {
|
|
804
|
-
linkPairs.push({
|
|
805
|
-
product_id: product.id,
|
|
806
|
-
product_option_id: optionId,
|
|
807
|
-
});
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
if (linkPairs.length > 0) {
|
|
811
|
-
await this.addProductOptionToProduct_(linkPairs, sharedContext);
|
|
812
|
-
}
|
|
813
|
-
const productIds = createdProducts.map((p) => p.id);
|
|
814
|
-
const productsWithOptions = await this.productService_.list({ id: productIds }, {
|
|
815
|
-
relations: [
|
|
816
|
-
"options",
|
|
817
|
-
"options.values",
|
|
818
|
-
"options.products",
|
|
819
|
-
"variants",
|
|
820
|
-
"images",
|
|
821
|
-
"tags",
|
|
822
|
-
],
|
|
823
|
-
}, sharedContext);
|
|
824
|
-
const productIdOrder = new Map(productIds.map((id, index) => [id, index]));
|
|
825
|
-
const orderedProductsWithOptions = [...productsWithOptions].sort((a, b) => (productIdOrder.get(a.id) ?? 0) - (productIdOrder.get(b.id) ?? 0));
|
|
826
|
-
return orderedProductsWithOptions;
|
|
675
|
+
const createdProducts = await this.productService_.create(productsToCreate, sharedContext);
|
|
676
|
+
return createdProducts;
|
|
827
677
|
}
|
|
828
678
|
async updateProducts_(data, sharedContext = {}) {
|
|
829
679
|
// We have to do that manually because this method is bypassing the product service and goes
|
|
@@ -836,69 +686,12 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
836
686
|
.getEventManager()
|
|
837
687
|
.registerSubscriber(new subscriber(sharedContext));
|
|
838
688
|
}
|
|
839
|
-
const
|
|
840
|
-
.
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
"options",
|
|
846
|
-
"options.values",
|
|
847
|
-
"options.products",
|
|
848
|
-
"variants",
|
|
849
|
-
"images",
|
|
850
|
-
"tags",
|
|
851
|
-
],
|
|
852
|
-
}, sharedContext),
|
|
853
|
-
allOptionIds.length
|
|
854
|
-
? this.productOptionService_.list({ id: allOptionIds }, {
|
|
855
|
-
relations: ["values", "products"],
|
|
856
|
-
}, sharedContext)
|
|
857
|
-
: Promise.resolve([]),
|
|
858
|
-
]);
|
|
859
|
-
if (allOptionIds.length && existingOptions.length !== allOptionIds.length) {
|
|
860
|
-
const found = new Set(existingOptions.map((opt) => opt.id));
|
|
861
|
-
const missing = allOptionIds.filter((id) => !found.has(id));
|
|
862
|
-
if (missing.length) {
|
|
863
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Some product options were not found: [${missing.join(", ")}]`);
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
const linkPairs = [];
|
|
867
|
-
const unlinkPairs = [];
|
|
868
|
-
for (const product of data) {
|
|
869
|
-
if (!product.option_ids) {
|
|
870
|
-
continue;
|
|
871
|
-
}
|
|
872
|
-
const newOptionIds = new Set(product.option_ids);
|
|
873
|
-
const existingOptionIds = new Set(originalProducts
|
|
874
|
-
.find((p) => p.id === product.id)
|
|
875
|
-
?.options?.map((o) => o.id) ?? []);
|
|
876
|
-
for (const optionId of newOptionIds) {
|
|
877
|
-
if (!existingOptionIds.has(optionId)) {
|
|
878
|
-
linkPairs.push({
|
|
879
|
-
product_id: product.id,
|
|
880
|
-
product_option_id: optionId,
|
|
881
|
-
});
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
for (const optionId of existingOptionIds) {
|
|
885
|
-
if (!newOptionIds.has(optionId)) {
|
|
886
|
-
unlinkPairs.push({
|
|
887
|
-
product_id: product.id,
|
|
888
|
-
product_option_id: optionId,
|
|
889
|
-
});
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
delete product.option_ids;
|
|
893
|
-
}
|
|
894
|
-
await Promise.all([
|
|
895
|
-
linkPairs.length &&
|
|
896
|
-
this.addProductOptionToProduct_(linkPairs, sharedContext),
|
|
897
|
-
unlinkPairs.length &&
|
|
898
|
-
this.removeProductOptionFromProduct_(unlinkPairs, sharedContext),
|
|
899
|
-
]);
|
|
900
|
-
await sharedContext.transactionManager.flush();
|
|
901
|
-
const normalizedProducts = this.normalizeUpdateProductInput(data);
|
|
689
|
+
const originalProducts = await this.productService_.list({
|
|
690
|
+
id: data.map((d) => d.id),
|
|
691
|
+
}, {
|
|
692
|
+
relations: ["options", "options.values", "variants", "images", "tags"],
|
|
693
|
+
}, sharedContext);
|
|
694
|
+
const normalizedProducts = await this.normalizeUpdateProductInput(data, originalProducts);
|
|
902
695
|
for (const product of normalizedProducts) {
|
|
903
696
|
this.validateProductUpdatePayload(product);
|
|
904
697
|
}
|
|
@@ -907,7 +700,7 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
907
700
|
}
|
|
908
701
|
// @ts-expect-error
|
|
909
702
|
async updateProductOptionValues(idOrSelector, data, sharedContext = {}) {
|
|
910
|
-
// TODO: There is a
|
|
703
|
+
// TODO: There is a missmatch in the API which lead to function with different number of
|
|
911
704
|
// arguments. Therefore, applying the MedusaContext() decorator to the function will not work
|
|
912
705
|
// because the context arg index will differ from method to method.
|
|
913
706
|
sharedContext.messageAggregator ??= new utils_1.MessageAggregator();
|
|
@@ -979,24 +772,10 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
979
772
|
validateProductUpdatePayload(productData) {
|
|
980
773
|
this.validateProductPayload(productData);
|
|
981
774
|
}
|
|
982
|
-
normalizeCreateProductInput(products, sharedContext = {}) {
|
|
775
|
+
async normalizeCreateProductInput(products, sharedContext = {}) {
|
|
983
776
|
const products_ = Array.isArray(products) ? products : [products];
|
|
984
|
-
const normalizedProducts = this.normalizeUpdateProductInput(products_);
|
|
777
|
+
const normalizedProducts = (await this.normalizeUpdateProductInput(products_));
|
|
985
778
|
for (const productData of normalizedProducts) {
|
|
986
|
-
if (productData.options?.length) {
|
|
987
|
-
;
|
|
988
|
-
productData.options = productData.options?.map((option) => {
|
|
989
|
-
return {
|
|
990
|
-
title: option.title,
|
|
991
|
-
values: option.values?.map((value) => {
|
|
992
|
-
return {
|
|
993
|
-
value: value,
|
|
994
|
-
};
|
|
995
|
-
}),
|
|
996
|
-
...(option.id ? { id: option.id } : {}),
|
|
997
|
-
};
|
|
998
|
-
});
|
|
999
|
-
}
|
|
1000
779
|
if (!productData.handle && productData.title) {
|
|
1001
780
|
productData.handle = (0, utils_1.toHandle)(productData.title);
|
|
1002
781
|
}
|
|
@@ -1037,18 +816,46 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
1037
816
|
* @param originalProducts - The original products to use for the normalization (must include options and option values relations)
|
|
1038
817
|
* @returns The normalized products
|
|
1039
818
|
*/
|
|
1040
|
-
normalizeUpdateProductInput(products) {
|
|
819
|
+
async normalizeUpdateProductInput(products, originalProducts) {
|
|
1041
820
|
const products_ = Array.isArray(products) ? products : [products];
|
|
821
|
+
const productsIds = products_.map((p) => p.id).filter(Boolean);
|
|
822
|
+
let dbOptions = [];
|
|
823
|
+
if (productsIds.length) {
|
|
824
|
+
// Re map options to handle non serialized data as well
|
|
825
|
+
dbOptions =
|
|
826
|
+
originalProducts
|
|
827
|
+
?.map((originalProduct) => originalProduct.options.map((option) => option))
|
|
828
|
+
.flat()
|
|
829
|
+
.filter(Boolean) ?? [];
|
|
830
|
+
}
|
|
1042
831
|
const normalizedProducts = [];
|
|
1043
832
|
for (const product of products_) {
|
|
1044
833
|
const productData = { ...product };
|
|
1045
834
|
if (productData.is_giftcard) {
|
|
1046
835
|
productData.discountable = false;
|
|
1047
836
|
}
|
|
837
|
+
if (productData.options?.length) {
|
|
838
|
+
;
|
|
839
|
+
productData.options = productData.options?.map((option) => {
|
|
840
|
+
const dbOption = dbOptions.find((o) => (o.title === option.title || o.id === option.id) &&
|
|
841
|
+
o.product_id === productData.id);
|
|
842
|
+
return {
|
|
843
|
+
title: option.title,
|
|
844
|
+
values: option.values?.map((value) => {
|
|
845
|
+
const dbValue = dbOption?.values?.find((val) => val.value === value);
|
|
846
|
+
return {
|
|
847
|
+
value: value,
|
|
848
|
+
...(dbValue ? { id: dbValue.id } : {}),
|
|
849
|
+
};
|
|
850
|
+
}),
|
|
851
|
+
...(dbOption ? { id: dbOption.id } : {}),
|
|
852
|
+
};
|
|
853
|
+
});
|
|
854
|
+
}
|
|
1048
855
|
if (productData.tag_ids) {
|
|
1049
856
|
;
|
|
1050
|
-
productData.tags = productData.tag_ids.map((
|
|
1051
|
-
id:
|
|
857
|
+
productData.tags = productData.tag_ids.map((cid) => ({
|
|
858
|
+
id: cid,
|
|
1052
859
|
}));
|
|
1053
860
|
delete productData.tag_ids;
|
|
1054
861
|
}
|
|
@@ -1083,10 +890,7 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
1083
890
|
const variantsWithOptions = ProductModuleService.assignOptionsToVariants(variants.map((v) => ({
|
|
1084
891
|
...v,
|
|
1085
892
|
// adding product_id to the variant to make it valid for the assignOptionsToVariants function
|
|
1086
|
-
|
|
1087
|
-
...(options.length && options[0].products?.length
|
|
1088
|
-
? { product_id: options[0].products[0].id }
|
|
1089
|
-
: {}),
|
|
893
|
+
...(options.length ? { product_id: options[0].product_id } : {}),
|
|
1090
894
|
})), options);
|
|
1091
895
|
ProductModuleService.checkIfVariantsHaveUniqueOptionsCombinations(variantsWithOptions);
|
|
1092
896
|
}
|
|
@@ -1096,13 +900,7 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
|
|
|
1096
900
|
}
|
|
1097
901
|
const variantsWithOptions = variants.map((variant) => {
|
|
1098
902
|
const numOfProvidedVariantOptionValues = Object.keys(variant.options || {}).length;
|
|
1099
|
-
const productsOptions = options.filter((o) =>
|
|
1100
|
-
// products could be a Collection object or array, normalize to array
|
|
1101
|
-
const productsArray = Array.isArray(o.products)
|
|
1102
|
-
? o.products
|
|
1103
|
-
: o.products?.toArray?.() ?? [];
|
|
1104
|
-
return productsArray.some((p) => p.id === variant.product_id);
|
|
1105
|
-
});
|
|
903
|
+
const productsOptions = options.filter((o) => o.product_id === variant.product_id);
|
|
1106
904
|
if (numOfProvidedVariantOptionValues &&
|
|
1107
905
|
productsOptions.length !== numOfProvidedVariantOptionValues) {
|
|
1108
906
|
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Product has ${productsOptions.length} option values but there were ${numOfProvidedVariantOptionValues} provided option values for the variant: ${variant.title}.`);
|
|
@@ -1514,36 +1312,6 @@ __decorate([
|
|
|
1514
1312
|
__metadata("design:paramtypes", [Array, Object]),
|
|
1515
1313
|
__metadata("design:returntype", Promise)
|
|
1516
1314
|
], ProductModuleService.prototype, "updateOptions_", null);
|
|
1517
|
-
__decorate([
|
|
1518
|
-
(0, utils_1.InjectManager)(),
|
|
1519
|
-
(0, utils_1.EmitEvents)(),
|
|
1520
|
-
__param(1, (0, utils_1.MedusaContext)()),
|
|
1521
|
-
__metadata("design:type", Function),
|
|
1522
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
1523
|
-
__metadata("design:returntype", Promise)
|
|
1524
|
-
], ProductModuleService.prototype, "addProductOptionToProduct", null);
|
|
1525
|
-
__decorate([
|
|
1526
|
-
(0, utils_1.InjectTransactionManager)(),
|
|
1527
|
-
__param(1, (0, utils_1.MedusaContext)()),
|
|
1528
|
-
__metadata("design:type", Function),
|
|
1529
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
1530
|
-
__metadata("design:returntype", Promise)
|
|
1531
|
-
], ProductModuleService.prototype, "addProductOptionToProduct_", null);
|
|
1532
|
-
__decorate([
|
|
1533
|
-
(0, utils_1.InjectManager)(),
|
|
1534
|
-
(0, utils_1.EmitEvents)(),
|
|
1535
|
-
__param(1, (0, utils_1.MedusaContext)()),
|
|
1536
|
-
__metadata("design:type", Function),
|
|
1537
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
1538
|
-
__metadata("design:returntype", Promise)
|
|
1539
|
-
], ProductModuleService.prototype, "removeProductOptionFromProduct", null);
|
|
1540
|
-
__decorate([
|
|
1541
|
-
(0, utils_1.InjectTransactionManager)(),
|
|
1542
|
-
__param(1, (0, utils_1.MedusaContext)()),
|
|
1543
|
-
__metadata("design:type", Function),
|
|
1544
|
-
__metadata("design:paramtypes", [Object, Object]),
|
|
1545
|
-
__metadata("design:returntype", Promise)
|
|
1546
|
-
], ProductModuleService.prototype, "removeProductOptionFromProduct_", null);
|
|
1547
1315
|
__decorate([
|
|
1548
1316
|
(0, utils_1.InjectManager)(),
|
|
1549
1317
|
(0, utils_1.EmitEvents)()
|
|
@@ -1677,6 +1445,16 @@ __decorate([
|
|
|
1677
1445
|
__metadata("design:paramtypes", [Array, Object]),
|
|
1678
1446
|
__metadata("design:returntype", Promise)
|
|
1679
1447
|
], ProductModuleService.prototype, "updateProducts_", null);
|
|
1448
|
+
__decorate([
|
|
1449
|
+
(0, utils_1.InjectManager)(),
|
|
1450
|
+
(0, utils_1.EmitEvents)()
|
|
1451
|
+
// @ts-expect-error
|
|
1452
|
+
,
|
|
1453
|
+
__param(2, (0, utils_1.MedusaContext)()),
|
|
1454
|
+
__metadata("design:type", Function),
|
|
1455
|
+
__metadata("design:paramtypes", [Object, Object, Object]),
|
|
1456
|
+
__metadata("design:returntype", Promise)
|
|
1457
|
+
], ProductModuleService.prototype, "updateProductOptionValues", null);
|
|
1680
1458
|
__decorate([
|
|
1681
1459
|
(0, utils_1.InjectTransactionManager)(),
|
|
1682
1460
|
__param(1, (0, utils_1.MedusaContext)()),
|
|
@@ -1688,7 +1466,7 @@ __decorate([
|
|
|
1688
1466
|
__param(1, (0, utils_1.MedusaContext)()),
|
|
1689
1467
|
__metadata("design:type", Function),
|
|
1690
1468
|
__metadata("design:paramtypes", [typeof (_a = typeof T !== "undefined" && T) === "function" ? _a : Object, Object]),
|
|
1691
|
-
__metadata("design:returntype",
|
|
1469
|
+
__metadata("design:returntype", Promise)
|
|
1692
1470
|
], ProductModuleService.prototype, "normalizeCreateProductInput", null);
|
|
1693
1471
|
__decorate([
|
|
1694
1472
|
(0, utils_1.InjectManager)()
|