@medusajs/product 3.0.0-snapshot-20251208164410 → 3.0.0-snapshot-20251211173847

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.
Files changed (69) hide show
  1. package/dist/migrations/Migration20250910154539.d.ts.map +1 -1
  2. package/dist/migrations/Migration20250910154539.js +0 -1
  3. package/dist/migrations/Migration20250910154539.js.map +1 -1
  4. package/dist/models/index.d.ts +0 -2
  5. package/dist/models/index.d.ts.map +1 -1
  6. package/dist/models/index.js +1 -5
  7. package/dist/models/index.js.map +1 -1
  8. package/dist/models/product-category.d.ts +6 -155
  9. package/dist/models/product-category.d.ts.map +1 -1
  10. package/dist/models/product-collection.d.ts +6 -155
  11. package/dist/models/product-collection.d.ts.map +1 -1
  12. package/dist/models/product-image.d.ts +14 -418
  13. package/dist/models/product-image.d.ts.map +1 -1
  14. package/dist/models/product-option-value.d.ts +12 -369
  15. package/dist/models/product-option-value.d.ts.map +1 -1
  16. package/dist/models/product-option-value.js +3 -14
  17. package/dist/models/product-option-value.js.map +1 -1
  18. package/dist/models/product-option.d.ts +6 -233
  19. package/dist/models/product-option.d.ts.map +1 -1
  20. package/dist/models/product-option.js +12 -4
  21. package/dist/models/product-option.js.map +1 -1
  22. package/dist/models/product-tag.d.ts +6 -155
  23. package/dist/models/product-tag.d.ts.map +1 -1
  24. package/dist/models/product-type.d.ts +6 -155
  25. package/dist/models/product-type.d.ts.map +1 -1
  26. package/dist/models/product-variant-product-image.d.ts +26 -780
  27. package/dist/models/product-variant-product-image.d.ts.map +1 -1
  28. package/dist/models/product-variant.d.ts +12 -362
  29. package/dist/models/product-variant.d.ts.map +1 -1
  30. package/dist/models/product.d.ts +6 -155
  31. package/dist/models/product.d.ts.map +1 -1
  32. package/dist/models/product.js +2 -7
  33. package/dist/models/product.js.map +1 -1
  34. package/dist/repositories/product-category.d.ts +15 -621
  35. package/dist/repositories/product-category.d.ts.map +1 -1
  36. package/dist/repositories/product.d.ts +6 -171
  37. package/dist/repositories/product.d.ts.map +1 -1
  38. package/dist/repositories/product.js +5 -50
  39. package/dist/repositories/product.js.map +1 -1
  40. package/dist/services/product-module-service.d.ts +2 -35
  41. package/dist/services/product-module-service.d.ts.map +1 -1
  42. package/dist/services/product-module-service.js +76 -660
  43. package/dist/services/product-module-service.js.map +1 -1
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +4 -4
  46. package/dist/migrations/Migration20251022153442.d.ts +0 -6
  47. package/dist/migrations/Migration20251022153442.d.ts.map +0 -1
  48. package/dist/migrations/Migration20251022153442.js +0 -104
  49. package/dist/migrations/Migration20251022153442.js.map +0 -1
  50. package/dist/migrations/Migration20251029150809.d.ts +0 -6
  51. package/dist/migrations/Migration20251029150809.d.ts.map +0 -1
  52. package/dist/migrations/Migration20251029150809.js +0 -14
  53. package/dist/migrations/Migration20251029150809.js.map +0 -1
  54. package/dist/migrations/Migration20251110180907.d.ts +0 -6
  55. package/dist/migrations/Migration20251110180907.d.ts.map +0 -1
  56. package/dist/migrations/Migration20251110180907.js +0 -21
  57. package/dist/migrations/Migration20251110180907.js.map +0 -1
  58. package/dist/migrations/Migration20251113183352.d.ts +0 -6
  59. package/dist/migrations/Migration20251113183352.d.ts.map +0 -1
  60. package/dist/migrations/Migration20251113183352.js +0 -32
  61. package/dist/migrations/Migration20251113183352.js.map +0 -1
  62. package/dist/models/product-product-option-value.d.ts +0 -2213
  63. package/dist/models/product-product-option-value.d.ts.map +0 -1
  64. package/dist/models/product-product-option-value.js +0 -19
  65. package/dist/models/product-product-option-value.js.map +0 -1
  66. package/dist/models/product-product-option.d.ts +0 -1272
  67. package/dist/models/product-product-option.d.ts.map +0 -1
  68. package/dist/models/product-product-option.js +0 -24
  69. package/dist/models/product-product-option.js.map +0 -1
@@ -16,8 +16,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
16
16
  const types_1 = require("@medusajs/framework/types");
17
17
  const _models_1 = require("../models");
18
18
  const utils_1 = require("@medusajs/framework/utils");
19
- const joiner_config_1 = require("./../joiner-config");
20
19
  const events_1 = require("../utils/events");
20
+ const joiner_config_1 = require("./../joiner-config");
21
21
  class ProductModuleService extends (0, utils_1.MedusaService)({
22
22
  Product: _models_1.Product,
23
23
  ProductCategory: _models_1.ProductCategory,
@@ -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, productProductOptionService, productProductOptionValueService, productOptionValueService, productVariantProductImageService, [utils_1.Modules.EVENT_BUS]: eventBusModuleService, }, moduleDeclaration) {
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,8 +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
- this.productProductOptionValueService_ = productProductOptionValueService;
49
47
  this.productOptionValueService_ = productOptionValueService;
50
48
  this.productVariantProductImageService_ = productVariantProductImageService;
51
49
  this.eventBusModuleService_ = eventBusModuleService;
@@ -57,16 +55,10 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
57
55
  async retrieveProduct(productId, config, sharedContext) {
58
56
  const relationsSet = new Set(config?.relations ?? []);
59
57
  const shouldLoadVariantImages = relationsSet.has("variants.images");
60
- const shouldFilterOptionValues = relationsSet.has("options.values");
61
58
  if (shouldLoadVariantImages) {
62
59
  relationsSet.add("variants");
63
60
  relationsSet.add("images");
64
61
  }
65
- if (shouldFilterOptionValues) {
66
- relationsSet.add("options");
67
- relationsSet.add("product_options");
68
- relationsSet.add("product_options.values");
69
- }
70
62
  const product = await this.productService_.retrieve(productId, this.getProductFindConfig_({
71
63
  ...config,
72
64
  relations: Array.from(relationsSet),
@@ -74,9 +66,6 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
74
66
  if (shouldLoadVariantImages && product.variants && product.images) {
75
67
  await this.buildVariantImagesFromProduct(product.variants, product.images, sharedContext);
76
68
  }
77
- if (shouldFilterOptionValues) {
78
- this.filterOptionValuesByProduct(product);
79
- }
80
69
  return this.baseRepository_.serialize(product);
81
70
  }
82
71
  // @ts-ignore
@@ -87,11 +76,6 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
87
76
  relationsSet.add("variants");
88
77
  relationsSet.add("images");
89
78
  }
90
- const shouldFilterOptionValues = relationsSet.has("options.values");
91
- if (shouldFilterOptionValues) {
92
- relationsSet.add("product_options");
93
- relationsSet.add("product_options.values");
94
- }
95
79
  const products = await this.productService_.list(filters, this.getProductFindConfig_({
96
80
  ...config,
97
81
  relations: Array.from(relationsSet),
@@ -103,15 +87,11 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
103
87
  }
104
88
  }
105
89
  }
106
- if (shouldFilterOptionValues) {
107
- this.filterOptionValuesByProducts(products);
108
- }
109
90
  return this.baseRepository_.serialize(products);
110
91
  }
111
92
  // @ts-ignore
112
93
  async listAndCountProducts(filters, config, sharedContext) {
113
94
  const shouldLoadVariantImages = config?.relations?.includes("variants.images");
114
- const shouldFilterOptionValues = config?.relations?.includes("options.values");
115
95
  // Ensure we load necessary relations
116
96
  const relations = [...(config?.relations || [])];
117
97
  if (shouldLoadVariantImages) {
@@ -122,14 +102,6 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
122
102
  relations.push("images");
123
103
  }
124
104
  }
125
- if (shouldFilterOptionValues) {
126
- if (!relations.includes("product_options")) {
127
- relations.push("product_options");
128
- }
129
- if (!relations.includes("product_options.values")) {
130
- relations.push("product_options.values");
131
- }
132
- }
133
105
  const [products, count] = await this.productService_.listAndCount(filters, this.getProductFindConfig_({ ...config, relations }), sharedContext);
134
106
  if (shouldLoadVariantImages) {
135
107
  for (const product of products) {
@@ -138,9 +110,6 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
138
110
  }
139
111
  }
140
112
  }
141
- if (shouldFilterOptionValues) {
142
- this.filterOptionValuesByProducts(products);
143
- }
144
113
  const serializedProducts = await this.baseRepository_.serialize(products);
145
114
  return [serializedProducts, count];
146
115
  }
@@ -173,11 +142,9 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
173
142
  throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Unable to create variants without specifying a product_id");
174
143
  }
175
144
  const productOptions = await this.productOptionService_.list({
176
- products: {
177
- id: [...new Set(data.map((v) => v.product_id))],
178
- },
145
+ product_id: [...new Set(data.map((v) => v.product_id))],
179
146
  }, {
180
- relations: ["values", "products"],
147
+ relations: ["values"],
181
148
  }, sharedContext);
182
149
  const variants = await this.productVariantService_.list({
183
150
  product_id: [...new Set(data.map((v) => v.product_id))],
@@ -237,10 +204,8 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
237
204
  product_id: v.product_id,
238
205
  }));
239
206
  const productOptions = await this.productOptionService_.list({
240
- products: {
241
- id: Array.from(new Set(variantsWithProductId.map((v) => v.product_id))),
242
- },
243
- }, { relations: ["values", "products"] }, sharedContext);
207
+ product_id: Array.from(new Set(variantsWithProductId.map((v) => v.product_id))),
208
+ }, { relations: ["values"] }, sharedContext);
244
209
  const productVariantsWithOptions = ProductModuleService.assignOptionsToVariants(variantsWithProductId, productOptions);
245
210
  if (data.some((d) => !!d.options)) {
246
211
  ProductModuleService.checkIfVariantWithOptionsAlreadyExists(productVariantsWithOptions, allVariants);
@@ -348,25 +313,18 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
348
313
  return Array.isArray(data) ? createdOptions : createdOptions[0];
349
314
  }
350
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
+ }
351
319
  const normalizedInput = data.map((opt) => {
352
- Object.keys(opt.ranks ?? []).forEach((value) => {
353
- if (!opt.values.includes(value)) {
354
- 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.`);
355
- }
356
- });
357
320
  return {
358
321
  ...opt,
359
322
  values: opt.values?.map((v) => {
360
- // Normalize each value into an object and attach rank if available
361
- const valueObj = (0, utils_1.isString)(v) ? { value: v } : v;
362
- const rank = opt.ranks && (0, utils_1.isString)(v)
363
- ? opt.ranks[v]
364
- : opt.ranks?.[valueObj.value];
365
- return rank !== undefined ? { ...valueObj, rank } : valueObj;
323
+ return typeof v === "string" ? { value: v } : v;
366
324
  }),
367
325
  };
368
326
  });
369
- return this.productOptionService_.create(normalizedInput, sharedContext);
327
+ return await this.productOptionService_.create(normalizedInput, sharedContext);
370
328
  }
371
329
  async upsertProductOptions(data, sharedContext = {}) {
372
330
  const input = Array.isArray(data) ? data : [data];
@@ -413,255 +371,35 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
413
371
  }
414
372
  // Data normalization
415
373
  const normalizedInput = data.map((opt) => {
416
- const dbOption = dbOptions.find(({ id }) => id === opt.id);
417
- const dbValues = dbOption?.values || [];
418
- if (opt.ranks) {
419
- const validValues = opt.values ?? dbValues.map((v) => v.value);
420
- Object.keys(opt.ranks).forEach((value) => {
421
- if (!validValues.includes(value)) {
422
- 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.`);
423
- }
424
- });
425
- }
426
- let normalizedValues;
427
- if (opt.values) {
428
- // If new values are provided → normalize and apply ranks
429
- normalizedValues = opt.values.map((v) => {
430
- const valueObj = (0, utils_1.isString)(v) ? { value: v } : v;
431
- const rank = opt.ranks && (0, utils_1.isString)(v)
432
- ? opt.ranks[v]
433
- : opt.ranks?.[valueObj.value];
434
- const rankedValue = rank !== undefined ? { ...valueObj, rank } : valueObj;
435
- if ("id" in rankedValue) {
436
- return rankedValue;
437
- }
438
- const dbVal = dbValues.find((dbVal) => dbVal.value === rankedValue.value);
439
- if (!dbVal) {
440
- return rankedValue;
441
- }
442
- return {
443
- id: dbVal.id,
444
- ...rankedValue,
445
- };
446
- });
447
- }
448
- else if (opt.ranks) {
449
- // If only ranks were provided → update existing DB values with ranks
450
- normalizedValues = dbValues.map((dbVal) => {
451
- const rank = opt.ranks[dbVal.value];
452
- return rank !== undefined
453
- ? { id: dbVal.id, value: dbVal.value, rank }
454
- : { id: dbVal.id, value: dbVal.value };
455
- });
456
- }
457
- 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
+ });
458
378
  return {
459
- ...cleanOpt,
460
- ...(normalizedValues ? { values: 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
+ : {}),
461
398
  };
462
399
  });
463
400
  const { entities: productOptions } = await this.productOptionService_.upsertWithReplace(normalizedInput, { relations: ["values"] }, sharedContext);
464
401
  return productOptions;
465
402
  }
466
- async addProductOptionToProduct(data, sharedContext = {}) {
467
- const productOptionProducts = await this.addProductOptionToProduct_(data, sharedContext);
468
- return productOptionProducts;
469
- }
470
- async addProductOptionToProduct_(data, sharedContext = {}) {
471
- const pairs = Array.isArray(data) ? data : [data];
472
- const existingProductOptions = await this.productProductOptionService_.list({
473
- $or: pairs.map((pair) => ({
474
- product_id: pair.product_id,
475
- product_option_id: pair.product_option_id,
476
- })),
477
- }, { relations: ["values"] }, sharedContext);
478
- // Validate value removals when product_option_value_ids are provided - this sets new values for the product <> options meaning some values may be removed thus we need removal here as well
479
- const validationPairs = [];
480
- for (const pair of pairs) {
481
- if (pair.product_option_value_ids) {
482
- const existingProductOption = existingProductOptions.find((epo) => epo.product_id === pair.product_id &&
483
- epo.product_option_id === pair.product_option_id);
484
- if (existingProductOption) {
485
- const currentValues = Array.isArray(existingProductOption.values)
486
- ? existingProductOption.values
487
- : existingProductOption.values?.toArray?.() ?? [];
488
- const currentValueIds = new Set(currentValues.map((v) => v.id));
489
- const newValueIds = new Set(pair.product_option_value_ids);
490
- // Find values being removed
491
- const removedValueIds = Array.from(currentValueIds).filter((id) => !newValueIds.has(id));
492
- if (removedValueIds.length > 0) {
493
- validationPairs.push({
494
- productId: pair.product_id,
495
- optionId: pair.product_option_id,
496
- valueIdsToCheck: removedValueIds,
497
- });
498
- }
499
- }
500
- }
501
- }
502
- if (validationPairs.length > 0) {
503
- await this.validateOptionRemoval_(validationPairs, sharedContext);
504
- }
505
- // Separate pairs: those that need PPO creation vs those that just need value updates
506
- const pairsNeedingPPOCreation = [];
507
- for (const pair of pairs) {
508
- const hasExistingPPO = existingProductOptions.some((epo) => epo.product_id === pair.product_id &&
509
- epo.product_option_id === pair.product_option_id);
510
- // Only create PPO if it doesn't exist
511
- if (!hasExistingPPO) {
512
- pairsNeedingPPOCreation.push(pair);
513
- }
514
- }
515
- let createdPPOs = [];
516
- if (pairsNeedingPPOCreation.length > 0) {
517
- const productProductOptions = await this.productProductOptionService_.create(pairsNeedingPPOCreation, sharedContext);
518
- createdPPOs = (Array.isArray(productProductOptions)
519
- ? productProductOptions
520
- : [productProductOptions]);
521
- }
522
- // Map all PPOs (existing and newly created) to their pairs
523
- const ppoMap = new Map();
524
- // First, add existing PPOs (these take precedence for value updates)
525
- for (const existingPPO of existingProductOptions) {
526
- const key = `${existingPPO.product_id}_${existingPPO.product_option_id}`;
527
- ppoMap.set(key, existingPPO);
528
- }
529
- // Then add newly created PPOs (only if they don't already exist in the map)
530
- for (const ppo of createdPPOs) {
531
- const key = `${ppo.product_id}_${ppo.product_option_id}`;
532
- if (!ppoMap.has(key)) {
533
- ppoMap.set(key, ppo);
534
- }
535
- }
536
- const uniqueOptionIds = [...new Set(pairs.map((p) => p.product_option_id))];
537
- const options = await this.productOptionService_.list({ id: uniqueOptionIds }, { relations: ["values"] }, sharedContext);
538
- const optionValuesMap = new Map(options.map((opt) => [opt.id, opt.values || []]));
539
- const valuePairsToCreate = [];
540
- for (const pair of pairs) {
541
- const key = `${pair.product_id}_${pair.product_option_id}`;
542
- const ppo = ppoMap.get(key);
543
- if (!ppo)
544
- continue;
545
- const originalPair = pair;
546
- if (originalPair) {
547
- const allValues = optionValuesMap.get(originalPair.product_option_id) || [];
548
- // If specific value IDs were provided, use only those; otherwise use all values
549
- const valuesToLink = originalPair.product_option_value_ids
550
- ? allValues.filter((v) => originalPair.product_option_value_ids.includes(v.id))
551
- : allValues;
552
- // If updating with specific value_ids, remove old values that aren't in the new list
553
- if (originalPair.product_option_value_ids) {
554
- const existingProductOption = existingProductOptions.find((epo) => epo.product_id === originalPair.product_id &&
555
- epo.product_option_id === originalPair.product_option_id);
556
- if (existingProductOption) {
557
- const currentValues = Array.isArray(existingProductOption.values)
558
- ? existingProductOption.values
559
- : existingProductOption.values?.toArray?.() ?? [];
560
- const currentValueIds = new Set(currentValues.map((v) => v.id));
561
- const newValueIds = new Set(originalPair.product_option_value_ids);
562
- // Find values to remove
563
- const valuesToRemove = Array.from(currentValueIds).filter((id) => !newValueIds.has(id));
564
- // Delete removed value links
565
- if (valuesToRemove.length > 0) {
566
- await this.productProductOptionValueService_.delete({
567
- product_product_option_id: existingProductOption.id,
568
- product_option_value_id: valuesToRemove,
569
- }, sharedContext);
570
- // Flush to ensure deletion is persisted
571
- await sharedContext.transactionManager?.flush?.();
572
- }
573
- // refetch PPOs after deletion
574
- const [reloadedPPO] = await this.productProductOptionService_.list({
575
- id: existingProductOption.id,
576
- }, { relations: ["values"] }, sharedContext);
577
- const reloadedValues = reloadedPPO
578
- ? Array.isArray(reloadedPPO.values)
579
- ? reloadedPPO.values
580
- : reloadedPPO.values?.toArray?.() ?? []
581
- : [];
582
- const reloadedValueIds = new Set(reloadedValues.map((v) => v.id));
583
- // Only create links for values that don't already exist (check against reloaded values)
584
- const existingValueIdsSet = reloadedValueIds;
585
- for (const value of valuesToLink) {
586
- if (!existingValueIdsSet.has(value.id)) {
587
- valuePairsToCreate.push({
588
- product_product_option_id: existingProductOption.id,
589
- product_option_value_id: value.id,
590
- });
591
- }
592
- }
593
- }
594
- else {
595
- // No existing link, create all value links
596
- for (const value of valuesToLink) {
597
- valuePairsToCreate.push({
598
- product_product_option_id: ppo.id,
599
- product_option_value_id: value.id,
600
- });
601
- }
602
- }
603
- }
604
- else {
605
- // No specific value_ids, create all value links (only if PPO is newly created)
606
- if (!existingProductOptions.find((epo) => epo.product_id === pair.product_id &&
607
- epo.product_option_id === pair.product_option_id)) {
608
- for (const value of valuesToLink) {
609
- valuePairsToCreate.push({
610
- product_product_option_id: ppo.id,
611
- product_option_value_id: value.id,
612
- });
613
- }
614
- }
615
- }
616
- }
617
- }
618
- if (valuePairsToCreate.length > 0) {
619
- await this.productProductOptionValueService_.create(valuePairsToCreate, sharedContext);
620
- }
621
- // Get all PPOs (existing + created) for return value
622
- const allPPOsForReturn = [];
623
- for (const pair of pairs) {
624
- const key = `${pair.product_id}_${pair.product_option_id}`;
625
- const ppo = ppoMap.get(key);
626
- if (ppo) {
627
- allPPOsForReturn.push(ppo);
628
- }
629
- }
630
- if (Array.isArray(data)) {
631
- return allPPOsForReturn.map((ppo) => ({ id: ppo.id }));
632
- }
633
- return { id: allPPOsForReturn[0]?.id || createdPPOs[0]?.id };
634
- }
635
- async removeProductOptionFromProduct(data, sharedContext = {}) {
636
- await this.removeProductOptionFromProduct_(data, sharedContext);
637
- }
638
- async removeProductOptionFromProduct_(data, sharedContext = {}) {
639
- const pairs = Array.isArray(data) ? data : [data];
640
- const productOptionsProducts = await this.productProductOptionService_.list({
641
- $or: pairs,
642
- }, { relations: [] }, sharedContext);
643
- // Validate that no variants are using the options before removal
644
- const validationPairs = productOptionsProducts
645
- .map((productOptionProduct) => {
646
- const productId = productOptionProduct.product_id;
647
- const optionId = productOptionProduct.product_option_id;
648
- if (productId && optionId) {
649
- return {
650
- productId,
651
- optionId,
652
- // Check all values of the option
653
- };
654
- }
655
- return null;
656
- })
657
- .filter((p) => p !== null);
658
- if (validationPairs.length > 0) {
659
- await this.validateOptionRemoval_(validationPairs, sharedContext);
660
- }
661
- const productOptionsProductIds = productOptionsProducts.map(({ id }) => id);
662
- await this.productProductOptionValueService_.delete(productOptionsProductIds.map((id) => ({ product_product_option_id: id })), sharedContext);
663
- await this.productProductOptionService_.delete(productOptionsProductIds, sharedContext);
664
- }
665
403
  // @ts-expect-error
666
404
  async createProductCollections(data, sharedContext = {}) {
667
405
  const input = Array.isArray(data) ? data : [data];
@@ -886,41 +624,7 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
886
624
  return (0, utils_1.isString)(idOrSelector) ? updatedProducts[0] : updatedProducts;
887
625
  }
888
626
  async createProducts_(data, sharedContext = {}) {
889
- const existingOptionIds = data
890
- .flatMap((p) => p.options ?? [])
891
- .filter((o) => "id" in o)
892
- .map((o) => o.id);
893
- let existingOptions = [];
894
- if (existingOptionIds.length > 0) {
895
- existingOptions = await this.productOptionService_.list({ id: existingOptionIds }, { relations: ["values"] }, sharedContext);
896
- const fetchedIds = new Set(existingOptions.map((opt) => opt.id));
897
- const missingIds = existingOptionIds.filter((id) => !fetchedIds.has(id));
898
- if (missingIds.length) {
899
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Some product options were not found: [${missingIds.join(", ")}]`);
900
- }
901
- }
902
- const existingOptionsMap = new Map(existingOptions.map((opt) => [opt.id, opt]));
903
- const hydratedData = data.map((product) => {
904
- if (!product.options?.length)
905
- return product;
906
- const hydratedOptions = product.options.map((option) => {
907
- if ("id" in option) {
908
- const dbOption = existingOptionsMap.get(option.id);
909
- if (!dbOption) {
910
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Product option with id ${option.id} not found.`);
911
- }
912
- return {
913
- id: dbOption.id,
914
- title: dbOption.title,
915
- values: dbOption.values?.map((v) => ({ value: v.value })),
916
- value_ids: option.value_ids,
917
- };
918
- }
919
- return option;
920
- });
921
- return { ...product, options: hydratedOptions };
922
- });
923
- const normalizedProducts = (await this.normalizeCreateProductInput(hydratedData, sharedContext));
627
+ const normalizedProducts = await this.normalizeCreateProductInput(data, sharedContext);
924
628
  for (const product of normalizedProducts) {
925
629
  this.validateProductCreatePayload(product);
926
630
  }
@@ -934,7 +638,6 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
934
638
  }, {}, sharedContext);
935
639
  }
936
640
  const existingTagsMap = new Map(existingTags.map((tag) => [tag.id, tag]));
937
- const productOptionsToCreate = new Map();
938
641
  const productsToCreate = normalizedProducts.map((product) => {
939
642
  const productId = (0, utils_1.generateEntityId)(product.id, "prod");
940
643
  product.id = productId;
@@ -942,12 +645,6 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
942
645
  ;
943
646
  product.categories = product.categories.map((category) => category.id);
944
647
  }
945
- if (product.options?.length) {
946
- const newOptions = product.options.filter((o) => !("id" in o));
947
- if (newOptions.length) {
948
- productOptionsToCreate.set(productId, newOptions);
949
- }
950
- }
951
648
  if (product.variants?.length) {
952
649
  const normalizedVariants = product.variants.map((variant) => {
953
650
  const variantId = (0, utils_1.generateEntityId)(variant.id, "variant");
@@ -973,79 +670,10 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
973
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.`);
974
671
  });
975
672
  }
976
- delete product.options;
977
673
  return product;
978
674
  });
979
- const productToOptionIdsMap = new Map();
980
- const allOptionsWithIds = [];
981
- for (const [productId, options] of productOptionsToCreate.entries()) {
982
- const optionIds = [];
983
- for (const option of options) {
984
- const optionId = (0, utils_1.generateEntityId)(undefined, "opt");
985
- optionIds.push(optionId);
986
- allOptionsWithIds.push({
987
- ...option,
988
- id: optionId,
989
- });
990
- }
991
- productToOptionIdsMap.set(productId, optionIds);
992
- }
993
- const [createdProducts] = await Promise.all([
994
- this.productService_.create(productsToCreate, sharedContext),
995
- allOptionsWithIds.length > 0
996
- ? this.createOptions_(allOptionsWithIds, sharedContext)
997
- : Promise.resolve([]),
998
- ]);
999
- const linkPairs = [];
1000
- for (const product of createdProducts) {
1001
- const hydratedProduct = hydratedData.find((p) => p.title === product.title);
1002
- const existingOptions = [];
1003
- if (hydratedProduct?.options?.length) {
1004
- for (const option of hydratedProduct.options) {
1005
- if ("id" in option) {
1006
- existingOptions.push({
1007
- id: option.id,
1008
- value_ids: option.value_ids,
1009
- });
1010
- }
1011
- }
1012
- }
1013
- const newOptionIds = productToOptionIdsMap.get(product.id) ?? [];
1014
- const newOptions = newOptionIds.map((id) => ({ id }));
1015
- const allOptions = [...existingOptions, ...newOptions];
1016
- for (const option of allOptions) {
1017
- const pair = {
1018
- product_id: product.id,
1019
- product_option_id: option.id,
1020
- product_option_value_ids: option.value_ids
1021
- ? option.value_ids
1022
- : undefined,
1023
- };
1024
- linkPairs.push(pair);
1025
- }
1026
- }
1027
- if (linkPairs.length > 0) {
1028
- await this.addProductOptionToProduct_(linkPairs, sharedContext);
1029
- }
1030
- await sharedContext.transactionManager.flush();
1031
- const productIds = createdProducts.map((p) => p.id);
1032
- const productsWithOptions = await this.productService_.list({ id: productIds }, {
1033
- relations: [
1034
- "options",
1035
- "options.values",
1036
- "options.products",
1037
- "product_options",
1038
- "product_options.values",
1039
- "variants",
1040
- "images",
1041
- "tags",
1042
- ],
1043
- }, sharedContext);
1044
- // Filter option values to only include those associated with each product
1045
- this.filterOptionValuesByProducts(productsWithOptions);
1046
- const productIdOrder = new Map(productIds.map((id, index) => [id, index]));
1047
- const orderedProductsWithOptions = [...productsWithOptions].sort((a, b) => (productIdOrder.get(a.id) ?? 0) - (productIdOrder.get(b.id) ?? 0));
1048
- return orderedProductsWithOptions;
675
+ const createdProducts = await this.productService_.create(productsToCreate, sharedContext);
676
+ return createdProducts;
1049
677
  }
1050
678
  async updateProducts_(data, sharedContext = {}) {
1051
679
  // We have to do that manually because this method is bypassing the product service and goes
@@ -1058,73 +686,23 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
1058
686
  .getEventManager()
1059
687
  .registerSubscriber(new subscriber(sharedContext));
1060
688
  }
1061
- const allOptionIds = data
1062
- .flatMap((p) => p.option_ids ?? [])
1063
- .filter((id) => !!id);
1064
- const [originalProducts, existingOptions] = await Promise.all([
1065
- this.productService_.list({ id: data.map((d) => d.id) }, {
1066
- relations: ["options", "options.values", "options.products", "tags"],
1067
- }, sharedContext),
1068
- allOptionIds.length
1069
- ? this.productOptionService_.list({ id: allOptionIds }, {
1070
- relations: ["values", "products"],
1071
- }, sharedContext)
1072
- : Promise.resolve([]),
1073
- ]);
1074
- if (allOptionIds.length && existingOptions.length !== allOptionIds.length) {
1075
- const found = new Set(existingOptions.map((opt) => opt.id));
1076
- const missing = allOptionIds.filter((id) => !found.has(id));
1077
- if (missing.length) {
1078
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Some product options were not found: [${missing.join(", ")}]`);
1079
- }
1080
- }
1081
- const linkPairs = [];
1082
- const unlinkPairs = [];
1083
- for (const product of data) {
1084
- if (!product.option_ids) {
1085
- continue;
1086
- }
1087
- const newOptionIds = new Set(product.option_ids);
1088
- const existingOptionIds = new Set(originalProducts
1089
- .find((p) => p.id === product.id)
1090
- ?.options?.map((o) => o.id) ?? []);
1091
- for (const optionId of newOptionIds) {
1092
- if (!existingOptionIds.has(optionId)) {
1093
- linkPairs.push({
1094
- product_id: product.id,
1095
- product_option_id: optionId,
1096
- });
1097
- }
1098
- }
1099
- for (const optionId of existingOptionIds) {
1100
- if (!newOptionIds.has(optionId)) {
1101
- unlinkPairs.push({
1102
- product_id: product.id,
1103
- product_option_id: optionId,
1104
- });
1105
- }
1106
- }
1107
- delete product.option_ids;
1108
- }
1109
- await Promise.all([
1110
- linkPairs.length &&
1111
- this.addProductOptionToProduct_(linkPairs, sharedContext),
1112
- unlinkPairs.length &&
1113
- this.removeProductOptionFromProduct_(unlinkPairs, sharedContext),
1114
- ]);
1115
- await sharedContext.transactionManager.flush();
1116
- const normalizedProducts = (await this.normalizeUpdateProductInput(data));
689
+ const productIds = data.map((d) => d.id).filter(Boolean);
690
+ const originalProducts = await this.productService_.list({
691
+ id: productIds,
692
+ }, {
693
+ relations: ["options", "options.values", "tags"],
694
+ take: productIds.length,
695
+ }, sharedContext);
696
+ const normalizedProducts = await this.normalizeUpdateProductInput(data, originalProducts);
1117
697
  for (const product of normalizedProducts) {
1118
698
  this.validateProductUpdatePayload(product);
1119
699
  }
1120
700
  const updatedProducts = await this.productRepository_.deepUpdate(normalizedProducts, ProductModuleService.validateVariantOptions, sharedContext);
1121
- // Filter option values to only include those associated with each product
1122
- this.filterOptionValuesByProducts(updatedProducts);
1123
701
  return updatedProducts;
1124
702
  }
1125
703
  // @ts-expect-error
1126
704
  async updateProductOptionValues(idOrSelector, data, sharedContext = {}) {
1127
- // TODO: There is a mismatch in the API which lead to function with different number of
705
+ // TODO: There is a missmatch in the API which lead to function with different number of
1128
706
  // arguments. Therefore, applying the MedusaContext() decorator to the function will not work
1129
707
  // because the context arg index will differ from method to method.
1130
708
  sharedContext.messageAggregator ??= new utils_1.MessageAggregator();
@@ -1199,22 +777,7 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
1199
777
  async normalizeCreateProductInput(products, sharedContext = {}) {
1200
778
  const products_ = Array.isArray(products) ? products : [products];
1201
779
  const normalizedProducts = (await this.normalizeUpdateProductInput(products_));
1202
- for await (const productData of normalizedProducts) {
1203
- if (productData.options?.length) {
1204
- ;
1205
- productData.options = productData.options?.map((option) => {
1206
- return {
1207
- title: option.title,
1208
- values: option.values?.map((value) => {
1209
- return {
1210
- value: value,
1211
- };
1212
- }),
1213
- is_exclusive: option.is_exclusive ?? true, // Always default to true for options created from product creation
1214
- ...(option.id ? { id: option.id } : {}),
1215
- };
1216
- });
1217
- }
780
+ for (const productData of normalizedProducts) {
1218
781
  if (!productData.handle && productData.title) {
1219
782
  productData.handle = (0, utils_1.toHandle)(productData.title);
1220
783
  }
@@ -1257,12 +820,39 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
1257
820
  */
1258
821
  async normalizeUpdateProductInput(products, originalProducts) {
1259
822
  const products_ = Array.isArray(products) ? products : [products];
823
+ const productsIds = products_.map((p) => p.id).filter(Boolean);
824
+ let dbOptions = [];
825
+ if (productsIds.length) {
826
+ // Re map options to handle non serialized data as well
827
+ dbOptions =
828
+ originalProducts
829
+ ?.flatMap((originalProduct) => originalProduct.options.map((option) => option))
830
+ .filter(Boolean) ?? [];
831
+ }
1260
832
  const normalizedProducts = [];
1261
833
  for (const product of products_) {
1262
834
  const productData = { ...product };
1263
835
  if (productData.is_giftcard) {
1264
836
  productData.discountable = false;
1265
837
  }
838
+ if (productData.options?.length) {
839
+ ;
840
+ productData.options = productData.options?.map((option) => {
841
+ const dbOption = dbOptions.find((o) => (o.title === option.title || o.id === option.id) &&
842
+ o.product_id === productData.id);
843
+ return {
844
+ title: option.title,
845
+ values: option.values?.map((value) => {
846
+ const dbValue = dbOption?.values?.find((val) => val.value === value);
847
+ return {
848
+ value: value,
849
+ ...(dbValue ? { id: dbValue.id } : {}),
850
+ };
851
+ }),
852
+ ...(dbOption ? { id: dbOption.id } : {}),
853
+ };
854
+ });
855
+ }
1266
856
  if (productData.tag_ids) {
1267
857
  ;
1268
858
  productData.tags = productData.tag_ids.map((cid) => ({
@@ -1301,10 +891,7 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
1301
891
  const variantsWithOptions = ProductModuleService.assignOptionsToVariants(variants.map((v) => ({
1302
892
  ...v,
1303
893
  // adding product_id to the variant to make it valid for the assignOptionsToVariants function
1304
- // get product_id from the first product in the products array of the first option
1305
- ...(options.length && options[0].products?.length
1306
- ? { product_id: options[0].products[0].id }
1307
- : {}),
894
+ ...(options.length ? { product_id: options[0].product_id } : {}),
1308
895
  })), options);
1309
896
  ProductModuleService.checkIfVariantsHaveUniqueOptionsCombinations(variantsWithOptions);
1310
897
  }
@@ -1314,13 +901,7 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
1314
901
  }
1315
902
  const variantsWithOptions = variants.map((variant) => {
1316
903
  const numOfProvidedVariantOptionValues = Object.keys(variant.options || {}).length;
1317
- const productsOptions = options.filter((o) => {
1318
- // products could be a Collection object or array, normalize to array
1319
- const productsArray = Array.isArray(o.products)
1320
- ? o.products
1321
- : o.products?.toArray?.() ?? [];
1322
- return productsArray.some((p) => p.id === variant.product_id);
1323
- });
904
+ const productsOptions = options.filter((o) => o.product_id === variant.product_id);
1324
905
  if (numOfProvidedVariantOptionValues &&
1325
906
  productsOptions.length !== numOfProvidedVariantOptionValues) {
1326
907
  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}.`);
@@ -1519,134 +1100,6 @@ class ProductModuleService extends (0, utils_1.MedusaService)({
1519
1100
  }
1520
1101
  return result;
1521
1102
  }
1522
- /**
1523
- * Validates that no variants are using the specified option or option values
1524
- * before they are removed from a product.
1525
- *
1526
- * @param pairs - Array of validation pairs: { productId, optionId, valueIdsToCheck? }
1527
- * @param sharedContext - The shared context
1528
- * @throws MedusaError if any variants are using the option/values
1529
- */
1530
- async validateOptionRemoval_(pairs, sharedContext = {}) {
1531
- if (pairs.length === 0) {
1532
- return;
1533
- }
1534
- // Filter pairs that need validation (for option removal, check if option is linked)
1535
- const pairsToValidate = [];
1536
- // For option removals (no valueIdsToCheck), check if options are linked to products
1537
- const optionRemovalPairs = pairs.filter((p) => !p.valueIdsToCheck);
1538
- if (optionRemovalPairs.length > 0) {
1539
- const existingProductOptions = await this.productProductOptionService_.list({
1540
- $or: optionRemovalPairs.map((p) => ({
1541
- product_id: p.productId,
1542
- product_option_id: p.optionId,
1543
- })),
1544
- }, {}, sharedContext);
1545
- const existingPairsSet = new Set(existingProductOptions.map((epo) => `${epo.product_id}_${epo.product_option_id}`));
1546
- // Only validate pairs that are actually linked
1547
- for (const pair of optionRemovalPairs) {
1548
- const key = `${pair.productId}_${pair.optionId}`;
1549
- if (existingPairsSet.has(key)) {
1550
- pairsToValidate.push(pair);
1551
- }
1552
- }
1553
- }
1554
- // For value removals (with valueIdsToCheck), always validate
1555
- const valueRemovalPairs = pairs.filter((p) => p.valueIdsToCheck);
1556
- pairsToValidate.push(...valueRemovalPairs);
1557
- if (pairsToValidate.length === 0) {
1558
- return; // Nothing to validate
1559
- }
1560
- // Get all unique option IDs to fetch options with their values
1561
- const uniqueOptionIds = [...new Set(pairsToValidate.map((p) => p.optionId))];
1562
- const options = await this.productOptionService_.list({ id: uniqueOptionIds }, { relations: ["values"] }, sharedContext);
1563
- const optionsMap = new Map(options.map((opt) => [opt.id, opt]));
1564
- const bulkValidationPairs = [];
1565
- for (const pair of pairsToValidate) {
1566
- const option = optionsMap.get(pair.optionId);
1567
- if (!option) {
1568
- continue; // Option doesn't exist, skip
1569
- }
1570
- // if no subset is provided we check the whole option values
1571
- const valueIdsToValidate = pair.valueIdsToCheck
1572
- ? pair.valueIdsToCheck
1573
- : (option.values || []).map((v) => v.id);
1574
- if (valueIdsToValidate.length === 0) {
1575
- continue; // No values to check
1576
- }
1577
- bulkValidationPairs.push({
1578
- productId: pair.productId,
1579
- optionValueIds: valueIdsToValidate,
1580
- pair,
1581
- option,
1582
- });
1583
- }
1584
- if (bulkValidationPairs.length > 0) {
1585
- const conflictingVariantsMap = await this.productRepository_.checkVariantsUsingOptionValues(bulkValidationPairs.map((p) => ({
1586
- productId: p.productId,
1587
- optionValueIds: p.optionValueIds,
1588
- })), sharedContext);
1589
- for (const bulkPair of bulkValidationPairs) {
1590
- const allConflictingVariants = [];
1591
- for (const valueId of bulkPair.optionValueIds) {
1592
- const key = `${bulkPair.productId}_${valueId}`;
1593
- const variants = conflictingVariantsMap.get(key) || [];
1594
- // Deduplicate variants by variant_id
1595
- for (const variant of variants) {
1596
- if (!allConflictingVariants.some((v) => v.variant_id === variant.variant_id)) {
1597
- allConflictingVariants.push({
1598
- variant_id: variant.variant_id,
1599
- title: variant.title,
1600
- });
1601
- }
1602
- }
1603
- }
1604
- if (allConflictingVariants.length > 0) {
1605
- const variantNames = allConflictingVariants.map((v) => v.title || v.variant_id);
1606
- if (bulkPair.pair.valueIdsToCheck) {
1607
- // Specific values being removed
1608
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Cannot unassign option values from product because the following variant(s) are using it: ${variantNames.join(", ")}`);
1609
- }
1610
- else {
1611
- // Entire option being removed
1612
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Cannot unassign product option from product which has variants for that option`);
1613
- }
1614
- }
1615
- }
1616
- }
1617
- }
1618
- filterOptionValuesByProducts(products) {
1619
- for (const product of products) {
1620
- this.filterOptionValuesByProduct(product);
1621
- }
1622
- }
1623
- filterOptionValuesByProduct(product) {
1624
- if (!product.options || !product.product_options) {
1625
- return;
1626
- }
1627
- const productOptions = Array.isArray(product.product_options)
1628
- ? product.product_options
1629
- : product.product_options?.toArray?.() ?? [];
1630
- // Build a Set of value IDs that are actually associated with this product
1631
- const allowedValueIds = new Set();
1632
- for (const productOption of productOptions) {
1633
- const values = Array.isArray(productOption.values)
1634
- ? productOption.values
1635
- : productOption.values?.toArray?.() ?? [];
1636
- for (const value of values) {
1637
- allowedValueIds.add(value.id);
1638
- }
1639
- }
1640
- // Filter the values in each option to only include allowed ones
1641
- if (product.options) {
1642
- for (const option of product.options) {
1643
- if (option.values) {
1644
- option.values = option.values.filter((value) => allowedValueIds.has(value.id));
1645
- }
1646
- }
1647
- }
1648
- delete product.product_options;
1649
- }
1650
1103
  async buildVariantImagesFromProduct(variants, productImages, sharedContext = {}) {
1651
1104
  // Create a clean map of images without problematic collections
1652
1105
  const imagesMap = new Map();
@@ -1860,36 +1313,6 @@ __decorate([
1860
1313
  __metadata("design:paramtypes", [Array, Object]),
1861
1314
  __metadata("design:returntype", Promise)
1862
1315
  ], ProductModuleService.prototype, "updateOptions_", null);
1863
- __decorate([
1864
- (0, utils_1.InjectManager)(),
1865
- (0, utils_1.EmitEvents)(),
1866
- __param(1, (0, utils_1.MedusaContext)()),
1867
- __metadata("design:type", Function),
1868
- __metadata("design:paramtypes", [Object, Object]),
1869
- __metadata("design:returntype", Promise)
1870
- ], ProductModuleService.prototype, "addProductOptionToProduct", null);
1871
- __decorate([
1872
- (0, utils_1.InjectTransactionManager)(),
1873
- __param(1, (0, utils_1.MedusaContext)()),
1874
- __metadata("design:type", Function),
1875
- __metadata("design:paramtypes", [Object, Object]),
1876
- __metadata("design:returntype", Promise)
1877
- ], ProductModuleService.prototype, "addProductOptionToProduct_", null);
1878
- __decorate([
1879
- (0, utils_1.InjectManager)(),
1880
- (0, utils_1.EmitEvents)(),
1881
- __param(1, (0, utils_1.MedusaContext)()),
1882
- __metadata("design:type", Function),
1883
- __metadata("design:paramtypes", [Object, Object]),
1884
- __metadata("design:returntype", Promise)
1885
- ], ProductModuleService.prototype, "removeProductOptionFromProduct", null);
1886
- __decorate([
1887
- (0, utils_1.InjectTransactionManager)(),
1888
- __param(1, (0, utils_1.MedusaContext)()),
1889
- __metadata("design:type", Function),
1890
- __metadata("design:paramtypes", [Object, Object]),
1891
- __metadata("design:returntype", Promise)
1892
- ], ProductModuleService.prototype, "removeProductOptionFromProduct_", null);
1893
1316
  __decorate([
1894
1317
  (0, utils_1.InjectManager)(),
1895
1318
  (0, utils_1.EmitEvents)()
@@ -2107,11 +1530,4 @@ __decorate([
2107
1530
  __metadata("design:paramtypes", [Array, Object]),
2108
1531
  __metadata("design:returntype", Promise)
2109
1532
  ], ProductModuleService.prototype, "getVariantImages", null);
2110
- __decorate([
2111
- (0, utils_1.InjectTransactionManager)(),
2112
- __param(1, (0, utils_1.MedusaContext)()),
2113
- __metadata("design:type", Function),
2114
- __metadata("design:paramtypes", [Array, Object]),
2115
- __metadata("design:returntype", Promise)
2116
- ], ProductModuleService.prototype, "validateOptionRemoval_", null);
2117
1533
  //# sourceMappingURL=product-module-service.js.map