@endora-commerce/mod-catalog 0.100.0

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 (443) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +63 -0
  3. package/dist/admin/components/PackagingUnitsEditor.d.ts +12 -0
  4. package/dist/admin/components/PackagingUnitsEditor.d.ts.map +1 -0
  5. package/dist/admin/components/PackagingUnitsEditor.js +99 -0
  6. package/dist/admin/components/PackagingUnitsEditor.js.map +1 -0
  7. package/dist/admin/components/ProductAttributesTab.d.ts +13 -0
  8. package/dist/admin/components/ProductAttributesTab.d.ts.map +1 -0
  9. package/dist/admin/components/ProductAttributesTab.js +140 -0
  10. package/dist/admin/components/ProductAttributesTab.js.map +1 -0
  11. package/dist/admin/components/ProductInventoryTab.d.ts +14 -0
  12. package/dist/admin/components/ProductInventoryTab.d.ts.map +1 -0
  13. package/dist/admin/components/ProductInventoryTab.js +284 -0
  14. package/dist/admin/components/ProductInventoryTab.js.map +1 -0
  15. package/dist/admin/components/ProductScopeEditor.d.ts +94 -0
  16. package/dist/admin/components/ProductScopeEditor.d.ts.map +1 -0
  17. package/dist/admin/components/ProductScopeEditor.js +395 -0
  18. package/dist/admin/components/ProductScopeEditor.js.map +1 -0
  19. package/dist/admin/components/ProductsBulkEditDialog.d.ts +11 -0
  20. package/dist/admin/components/ProductsBulkEditDialog.d.ts.map +1 -0
  21. package/dist/admin/components/ProductsBulkEditDialog.js +304 -0
  22. package/dist/admin/components/ProductsBulkEditDialog.js.map +1 -0
  23. package/dist/admin/index.d.ts +45 -0
  24. package/dist/admin/index.d.ts.map +1 -0
  25. package/dist/admin/index.js +184 -0
  26. package/dist/admin/index.js.map +1 -0
  27. package/dist/admin/lib/resolve-product-selection.d.ts +21 -0
  28. package/dist/admin/lib/resolve-product-selection.d.ts.map +1 -0
  29. package/dist/admin/lib/resolve-product-selection.js +25 -0
  30. package/dist/admin/lib/resolve-product-selection.js.map +1 -0
  31. package/dist/admin/pages/AttachmentTypesPage.d.ts +18 -0
  32. package/dist/admin/pages/AttachmentTypesPage.d.ts.map +1 -0
  33. package/dist/admin/pages/AttachmentTypesPage.js +92 -0
  34. package/dist/admin/pages/AttachmentTypesPage.js.map +1 -0
  35. package/dist/admin/pages/AttributeSetsPage.d.ts +21 -0
  36. package/dist/admin/pages/AttributeSetsPage.d.ts.map +1 -0
  37. package/dist/admin/pages/AttributeSetsPage.js +158 -0
  38. package/dist/admin/pages/AttributeSetsPage.js.map +1 -0
  39. package/dist/admin/pages/AttributesManager.d.ts +9 -0
  40. package/dist/admin/pages/AttributesManager.d.ts.map +1 -0
  41. package/dist/admin/pages/AttributesManager.js +305 -0
  42. package/dist/admin/pages/AttributesManager.js.map +1 -0
  43. package/dist/admin/pages/BulkOperationDetailPage.d.ts +9 -0
  44. package/dist/admin/pages/BulkOperationDetailPage.d.ts.map +1 -0
  45. package/dist/admin/pages/BulkOperationDetailPage.js +187 -0
  46. package/dist/admin/pages/BulkOperationDetailPage.js.map +1 -0
  47. package/dist/admin/pages/BulkOperationsPage.d.ts +9 -0
  48. package/dist/admin/pages/BulkOperationsPage.d.ts.map +1 -0
  49. package/dist/admin/pages/BulkOperationsPage.js +98 -0
  50. package/dist/admin/pages/BulkOperationsPage.js.map +1 -0
  51. package/dist/admin/pages/CategoriesTree.d.ts +9 -0
  52. package/dist/admin/pages/CategoriesTree.d.ts.map +1 -0
  53. package/dist/admin/pages/CategoriesTree.js +176 -0
  54. package/dist/admin/pages/CategoriesTree.js.map +1 -0
  55. package/dist/admin/pages/ProductEditor.d.ts +13 -0
  56. package/dist/admin/pages/ProductEditor.d.ts.map +1 -0
  57. package/dist/admin/pages/ProductEditor.js +1050 -0
  58. package/dist/admin/pages/ProductEditor.js.map +1 -0
  59. package/dist/admin/pages/ProductsList.d.ts +9 -0
  60. package/dist/admin/pages/ProductsList.d.ts.map +1 -0
  61. package/dist/admin/pages/ProductsList.js +399 -0
  62. package/dist/admin/pages/ProductsList.js.map +1 -0
  63. package/dist/backend/commands/attribute-commands.d.ts +111 -0
  64. package/dist/backend/commands/attribute-commands.d.ts.map +1 -0
  65. package/dist/backend/commands/attribute-commands.js +482 -0
  66. package/dist/backend/commands/attribute-commands.js.map +1 -0
  67. package/dist/backend/demo/reset.d.ts +23 -0
  68. package/dist/backend/demo/reset.d.ts.map +1 -0
  69. package/dist/backend/demo/reset.js +41 -0
  70. package/dist/backend/demo/reset.js.map +1 -0
  71. package/dist/backend/demo/rows.d.ts +103 -0
  72. package/dist/backend/demo/rows.d.ts.map +1 -0
  73. package/dist/backend/demo/rows.js +162 -0
  74. package/dist/backend/demo/rows.js.map +1 -0
  75. package/dist/backend/demo/seed.d.ts +35 -0
  76. package/dist/backend/demo/seed.d.ts.map +1 -0
  77. package/dist/backend/demo/seed.js +177 -0
  78. package/dist/backend/demo/seed.js.map +1 -0
  79. package/dist/backend/entities/attachment-type.entity.d.ts +16 -0
  80. package/dist/backend/entities/attachment-type.entity.d.ts.map +1 -0
  81. package/dist/backend/entities/attachment-type.entity.js +57 -0
  82. package/dist/backend/entities/attachment-type.entity.js.map +1 -0
  83. package/dist/backend/entities/attribute-set-attribute.entity.d.ts +26 -0
  84. package/dist/backend/entities/attribute-set-attribute.entity.d.ts.map +1 -0
  85. package/dist/backend/entities/attribute-set-attribute.entity.js +55 -0
  86. package/dist/backend/entities/attribute-set-attribute.entity.js.map +1 -0
  87. package/dist/backend/entities/attribute-set.entity.d.ts +22 -0
  88. package/dist/backend/entities/attribute-set.entity.d.ts.map +1 -0
  89. package/dist/backend/entities/attribute-set.entity.js +67 -0
  90. package/dist/backend/entities/attribute-set.entity.js.map +1 -0
  91. package/dist/backend/entities/bulk-operation.entity.d.ts +78 -0
  92. package/dist/backend/entities/bulk-operation.entity.d.ts.map +1 -0
  93. package/dist/backend/entities/bulk-operation.entity.js +138 -0
  94. package/dist/backend/entities/bulk-operation.entity.js.map +1 -0
  95. package/dist/backend/entities/bundle-slot-option.entity.d.ts +23 -0
  96. package/dist/backend/entities/bundle-slot-option.entity.d.ts.map +1 -0
  97. package/dist/backend/entities/bundle-slot-option.entity.js +68 -0
  98. package/dist/backend/entities/bundle-slot-option.entity.js.map +1 -0
  99. package/dist/backend/entities/bundle-slot.entity.d.ts +25 -0
  100. package/dist/backend/entities/bundle-slot.entity.d.ts.map +1 -0
  101. package/dist/backend/entities/bundle-slot.entity.js +74 -0
  102. package/dist/backend/entities/bundle-slot.entity.js.map +1 -0
  103. package/dist/backend/entities/category.entity.d.ts +26 -0
  104. package/dist/backend/entities/category.entity.d.ts.map +1 -0
  105. package/dist/backend/entities/category.entity.js +119 -0
  106. package/dist/backend/entities/category.entity.js.map +1 -0
  107. package/dist/backend/entities/gallery-item-label.entity.d.ts +22 -0
  108. package/dist/backend/entities/gallery-item-label.entity.d.ts.map +1 -0
  109. package/dist/backend/entities/gallery-item-label.entity.js +50 -0
  110. package/dist/backend/entities/gallery-item-label.entity.js.map +1 -0
  111. package/dist/backend/entities/gallery-item.entity.d.ts +17 -0
  112. package/dist/backend/entities/gallery-item.entity.d.ts.map +1 -0
  113. package/dist/backend/entities/gallery-item.entity.js +58 -0
  114. package/dist/backend/entities/gallery-item.entity.js.map +1 -0
  115. package/dist/backend/entities/grouped-item.entity.d.ts +23 -0
  116. package/dist/backend/entities/grouped-item.entity.d.ts.map +1 -0
  117. package/dist/backend/entities/grouped-item.entity.js +68 -0
  118. package/dist/backend/entities/grouped-item.entity.js.map +1 -0
  119. package/dist/backend/entities/product-attachment.entity.d.ts +23 -0
  120. package/dist/backend/entities/product-attachment.entity.d.ts.map +1 -0
  121. package/dist/backend/entities/product-attachment.entity.js +77 -0
  122. package/dist/backend/entities/product-attachment.entity.js.map +1 -0
  123. package/dist/backend/entities/product-attribute.entity.d.ts +72 -0
  124. package/dist/backend/entities/product-attribute.entity.d.ts.map +1 -0
  125. package/dist/backend/entities/product-attribute.entity.js +161 -0
  126. package/dist/backend/entities/product-attribute.entity.js.map +1 -0
  127. package/dist/backend/entities/product-editor-preference.entity.d.ts +28 -0
  128. package/dist/backend/entities/product-editor-preference.entity.d.ts.map +1 -0
  129. package/dist/backend/entities/product-editor-preference.entity.js +63 -0
  130. package/dist/backend/entities/product-editor-preference.entity.js.map +1 -0
  131. package/dist/backend/entities/product-link.entity.d.ts +25 -0
  132. package/dist/backend/entities/product-link.entity.d.ts.map +1 -0
  133. package/dist/backend/entities/product-link.entity.js +70 -0
  134. package/dist/backend/entities/product-link.entity.js.map +1 -0
  135. package/dist/backend/entities/product-packaging-unit.entity.d.ts +26 -0
  136. package/dist/backend/entities/product-packaging-unit.entity.d.ts.map +1 -0
  137. package/dist/backend/entities/product-packaging-unit.entity.js +76 -0
  138. package/dist/backend/entities/product-packaging-unit.entity.js.map +1 -0
  139. package/dist/backend/entities/product-value-override.entity.d.ts +43 -0
  140. package/dist/backend/entities/product-value-override.entity.d.ts.map +1 -0
  141. package/dist/backend/entities/product-value-override.entity.js +90 -0
  142. package/dist/backend/entities/product-value-override.entity.js.map +1 -0
  143. package/dist/backend/entities/product-variant.entity.d.ts +18 -0
  144. package/dist/backend/entities/product-variant.entity.d.ts.map +1 -0
  145. package/dist/backend/entities/product-variant.entity.js +68 -0
  146. package/dist/backend/entities/product-variant.entity.js.map +1 -0
  147. package/dist/backend/entities/product.entity.d.ts +108 -0
  148. package/dist/backend/entities/product.entity.d.ts.map +1 -0
  149. package/dist/backend/entities/product.entity.js +230 -0
  150. package/dist/backend/entities/product.entity.js.map +1 -0
  151. package/dist/backend/index.d.ts +262 -0
  152. package/dist/backend/index.d.ts.map +1 -0
  153. package/dist/backend/index.js +642 -0
  154. package/dist/backend/index.js.map +1 -0
  155. package/dist/backend/plugin.d.ts +216 -0
  156. package/dist/backend/plugin.d.ts.map +1 -0
  157. package/dist/backend/plugin.js +223 -0
  158. package/dist/backend/plugin.js.map +1 -0
  159. package/dist/backend/prompt-tools.d.ts +47 -0
  160. package/dist/backend/prompt-tools.d.ts.map +1 -0
  161. package/dist/backend/prompt-tools.js +284 -0
  162. package/dist/backend/prompt-tools.js.map +1 -0
  163. package/dist/backend/routes.admin.d.ts +105 -0
  164. package/dist/backend/routes.admin.d.ts.map +1 -0
  165. package/dist/backend/routes.admin.js +1162 -0
  166. package/dist/backend/routes.admin.js.map +1 -0
  167. package/dist/backend/routes.api-key.d.ts +33 -0
  168. package/dist/backend/routes.api-key.d.ts.map +1 -0
  169. package/dist/backend/routes.api-key.js +43 -0
  170. package/dist/backend/routes.api-key.js.map +1 -0
  171. package/dist/backend/routes.external.d.ts +32 -0
  172. package/dist/backend/routes.external.d.ts.map +1 -0
  173. package/dist/backend/routes.external.js +115 -0
  174. package/dist/backend/routes.external.js.map +1 -0
  175. package/dist/backend/routes.public.d.ts +46 -0
  176. package/dist/backend/routes.public.d.ts.map +1 -0
  177. package/dist/backend/routes.public.js +318 -0
  178. package/dist/backend/routes.public.js.map +1 -0
  179. package/dist/backend/services/asset-references.d.ts +4 -0
  180. package/dist/backend/services/asset-references.d.ts.map +1 -0
  181. package/dist/backend/services/asset-references.js +104 -0
  182. package/dist/backend/services/asset-references.js.map +1 -0
  183. package/dist/backend/services/attachment.service.d.ts +45 -0
  184. package/dist/backend/services/attachment.service.d.ts.map +1 -0
  185. package/dist/backend/services/attachment.service.js +268 -0
  186. package/dist/backend/services/attachment.service.js.map +1 -0
  187. package/dist/backend/services/attribute-option-validator.d.ts +47 -0
  188. package/dist/backend/services/attribute-option-validator.d.ts.map +1 -0
  189. package/dist/backend/services/attribute-option-validator.js +69 -0
  190. package/dist/backend/services/attribute-option-validator.js.map +1 -0
  191. package/dist/backend/services/attribute-set-validations.d.ts +65 -0
  192. package/dist/backend/services/attribute-set-validations.d.ts.map +1 -0
  193. package/dist/backend/services/attribute-set-validations.js +89 -0
  194. package/dist/backend/services/attribute-set-validations.js.map +1 -0
  195. package/dist/backend/services/attribute-set.service.d.ts +50 -0
  196. package/dist/backend/services/attribute-set.service.d.ts.map +1 -0
  197. package/dist/backend/services/attribute-set.service.js +401 -0
  198. package/dist/backend/services/attribute-set.service.js.map +1 -0
  199. package/dist/backend/services/attribute-type-mapping.d.ts +66 -0
  200. package/dist/backend/services/attribute-type-mapping.d.ts.map +1 -0
  201. package/dist/backend/services/attribute-type-mapping.js +121 -0
  202. package/dist/backend/services/attribute-type-mapping.js.map +1 -0
  203. package/dist/backend/services/attribute-value-key.service.d.ts +48 -0
  204. package/dist/backend/services/attribute-value-key.service.d.ts.map +1 -0
  205. package/dist/backend/services/attribute-value-key.service.js +118 -0
  206. package/dist/backend/services/attribute-value-key.service.js.map +1 -0
  207. package/dist/backend/services/audit-references.d.ts +13 -0
  208. package/dist/backend/services/audit-references.d.ts.map +1 -0
  209. package/dist/backend/services/audit-references.js +51 -0
  210. package/dist/backend/services/audit-references.js.map +1 -0
  211. package/dist/backend/services/bulk-operation-queue.d.ts +26 -0
  212. package/dist/backend/services/bulk-operation-queue.d.ts.map +1 -0
  213. package/dist/backend/services/bulk-operation-queue.js +34 -0
  214. package/dist/backend/services/bulk-operation-queue.js.map +1 -0
  215. package/dist/backend/services/bulk-operation.service.d.ts +195 -0
  216. package/dist/backend/services/bulk-operation.service.d.ts.map +1 -0
  217. package/dist/backend/services/bulk-operation.service.js +510 -0
  218. package/dist/backend/services/bulk-operation.service.js.map +1 -0
  219. package/dist/backend/services/bundle.service.d.ts +87 -0
  220. package/dist/backend/services/bundle.service.d.ts.map +1 -0
  221. package/dist/backend/services/bundle.service.js +286 -0
  222. package/dist/backend/services/bundle.service.js.map +1 -0
  223. package/dist/backend/services/catalog-admin.service.d.ts +398 -0
  224. package/dist/backend/services/catalog-admin.service.d.ts.map +1 -0
  225. package/dist/backend/services/catalog-admin.service.js +1516 -0
  226. package/dist/backend/services/catalog-admin.service.js.map +1 -0
  227. package/dist/backend/services/catalog-attribute-read.service.d.ts +78 -0
  228. package/dist/backend/services/catalog-attribute-read.service.d.ts.map +1 -0
  229. package/dist/backend/services/catalog-attribute-read.service.js +216 -0
  230. package/dist/backend/services/catalog-attribute-read.service.js.map +1 -0
  231. package/dist/backend/services/catalog-bulk-import.service.d.ts +30 -0
  232. package/dist/backend/services/catalog-bulk-import.service.d.ts.map +1 -0
  233. package/dist/backend/services/catalog-bulk-import.service.js +136 -0
  234. package/dist/backend/services/catalog-bulk-import.service.js.map +1 -0
  235. package/dist/backend/services/catalog-bulk-update.service.d.ts +91 -0
  236. package/dist/backend/services/catalog-bulk-update.service.d.ts.map +1 -0
  237. package/dist/backend/services/catalog-bulk-update.service.js +330 -0
  238. package/dist/backend/services/catalog-bulk-update.service.js.map +1 -0
  239. package/dist/backend/services/catalog-category-read.service.d.ts +66 -0
  240. package/dist/backend/services/catalog-category-read.service.d.ts.map +1 -0
  241. package/dist/backend/services/catalog-category-read.service.js +248 -0
  242. package/dist/backend/services/catalog-category-read.service.js.map +1 -0
  243. package/dist/backend/services/catalog-org-price-decorator.d.ts +90 -0
  244. package/dist/backend/services/catalog-org-price-decorator.d.ts.map +1 -0
  245. package/dist/backend/services/catalog-org-price-decorator.js +184 -0
  246. package/dist/backend/services/catalog-org-price-decorator.js.map +1 -0
  247. package/dist/backend/services/catalog-product-filter.service.d.ts +82 -0
  248. package/dist/backend/services/catalog-product-filter.service.d.ts.map +1 -0
  249. package/dist/backend/services/catalog-product-filter.service.js +275 -0
  250. package/dist/backend/services/catalog-product-filter.service.js.map +1 -0
  251. package/dist/backend/services/catalog-product-read.service.d.ts +46 -0
  252. package/dist/backend/services/catalog-product-read.service.d.ts.map +1 -0
  253. package/dist/backend/services/catalog-product-read.service.js +197 -0
  254. package/dist/backend/services/catalog-product-read.service.js.map +1 -0
  255. package/dist/backend/services/catalog-query.service.d.ts +444 -0
  256. package/dist/backend/services/catalog-query.service.d.ts.map +1 -0
  257. package/dist/backend/services/catalog-query.service.js +1633 -0
  258. package/dist/backend/services/catalog-query.service.js.map +1 -0
  259. package/dist/backend/services/catalog-quick-search.service.d.ts +78 -0
  260. package/dist/backend/services/catalog-quick-search.service.d.ts.map +1 -0
  261. package/dist/backend/services/catalog-quick-search.service.js +159 -0
  262. package/dist/backend/services/catalog-quick-search.service.js.map +1 -0
  263. package/dist/backend/services/catalog-write-ports.d.ts +25 -0
  264. package/dist/backend/services/catalog-write-ports.d.ts.map +1 -0
  265. package/dist/backend/services/catalog-write-ports.js +63 -0
  266. package/dist/backend/services/catalog-write-ports.js.map +1 -0
  267. package/dist/backend/services/category-admin.service.d.ts +102 -0
  268. package/dist/backend/services/category-admin.service.d.ts.map +1 -0
  269. package/dist/backend/services/category-admin.service.js +271 -0
  270. package/dist/backend/services/category-admin.service.js.map +1 -0
  271. package/dist/backend/services/gallery.service.d.ts +85 -0
  272. package/dist/backend/services/gallery.service.d.ts.map +1 -0
  273. package/dist/backend/services/gallery.service.js +326 -0
  274. package/dist/backend/services/gallery.service.js.map +1 -0
  275. package/dist/backend/services/grouped.service.d.ts +39 -0
  276. package/dist/backend/services/grouped.service.d.ts.map +1 -0
  277. package/dist/backend/services/grouped.service.js +136 -0
  278. package/dist/backend/services/grouped.service.js.map +1 -0
  279. package/dist/backend/services/label-resolver.d.ts +16 -0
  280. package/dist/backend/services/label-resolver.d.ts.map +1 -0
  281. package/dist/backend/services/label-resolver.js +43 -0
  282. package/dist/backend/services/label-resolver.js.map +1 -0
  283. package/dist/backend/services/packaging-unit.service.d.ts +28 -0
  284. package/dist/backend/services/packaging-unit.service.d.ts.map +1 -0
  285. package/dist/backend/services/packaging-unit.service.js +197 -0
  286. package/dist/backend/services/packaging-unit.service.js.map +1 -0
  287. package/dist/backend/services/primary-asset-url.d.ts +4 -0
  288. package/dist/backend/services/primary-asset-url.d.ts.map +1 -0
  289. package/dist/backend/services/primary-asset-url.js +55 -0
  290. package/dist/backend/services/primary-asset-url.js.map +1 -0
  291. package/dist/backend/services/product-editor-preferences.service.d.ts +20 -0
  292. package/dist/backend/services/product-editor-preferences.service.d.ts.map +1 -0
  293. package/dist/backend/services/product-editor-preferences.service.js +44 -0
  294. package/dist/backend/services/product-editor-preferences.service.js.map +1 -0
  295. package/dist/backend/services/product-link.service.d.ts +169 -0
  296. package/dist/backend/services/product-link.service.d.ts.map +1 -0
  297. package/dist/backend/services/product-link.service.js +297 -0
  298. package/dist/backend/services/product-link.service.js.map +1 -0
  299. package/dist/backend/services/product-overrides.service.d.ts +77 -0
  300. package/dist/backend/services/product-overrides.service.d.ts.map +1 -0
  301. package/dist/backend/services/product-overrides.service.js +204 -0
  302. package/dist/backend/services/product-overrides.service.js.map +1 -0
  303. package/dist/backend/services/product-scope-context.service.d.ts +36 -0
  304. package/dist/backend/services/product-scope-context.service.d.ts.map +1 -0
  305. package/dist/backend/services/product-scope-context.service.js +106 -0
  306. package/dist/backend/services/product-scope-context.service.js.map +1 -0
  307. package/dist/backend/services/product-type-validations.d.ts +42 -0
  308. package/dist/backend/services/product-type-validations.d.ts.map +1 -0
  309. package/dist/backend/services/product-type-validations.js +55 -0
  310. package/dist/backend/services/product-type-validations.js.map +1 -0
  311. package/dist/backend/services/product-value-resolver.service.d.ts +59 -0
  312. package/dist/backend/services/product-value-resolver.service.d.ts.map +1 -0
  313. package/dist/backend/services/product-value-resolver.service.js +111 -0
  314. package/dist/backend/services/product-value-resolver.service.js.map +1 -0
  315. package/dist/backend/services/system-attribute-scopes.d.ts +18 -0
  316. package/dist/backend/services/system-attribute-scopes.d.ts.map +1 -0
  317. package/dist/backend/services/system-attribute-scopes.js +18 -0
  318. package/dist/backend/services/system-attribute-scopes.js.map +1 -0
  319. package/dist/backend/services/viewer-organization.d.ts +25 -0
  320. package/dist/backend/services/viewer-organization.d.ts.map +1 -0
  321. package/dist/backend/services/viewer-organization.js +31 -0
  322. package/dist/backend/services/viewer-organization.js.map +1 -0
  323. package/dist/manifest.d.ts +204 -0
  324. package/dist/manifest.d.ts.map +1 -0
  325. package/dist/manifest.js +686 -0
  326. package/dist/manifest.js.map +1 -0
  327. package/dist/migrations/20260429T064146_catalog_attribute_sets_init.d.ts +33 -0
  328. package/dist/migrations/20260429T064146_catalog_attribute_sets_init.d.ts.map +1 -0
  329. package/dist/migrations/20260429T064146_catalog_attribute_sets_init.js +118 -0
  330. package/dist/migrations/20260429T064146_catalog_attribute_sets_init.js.map +1 -0
  331. package/dist/migrations/20260429T070004_catalog_product_attribute_extensions.d.ts +24 -0
  332. package/dist/migrations/20260429T070004_catalog_product_attribute_extensions.d.ts.map +1 -0
  333. package/dist/migrations/20260429T070004_catalog_product_attribute_extensions.js +31 -0
  334. package/dist/migrations/20260429T070004_catalog_product_attribute_extensions.js.map +1 -0
  335. package/dist/migrations/20260429T102322_catalog_product_type_and_virtual_fields.d.ts +32 -0
  336. package/dist/migrations/20260429T102322_catalog_product_type_and_virtual_fields.d.ts.map +1 -0
  337. package/dist/migrations/20260429T102322_catalog_product_type_and_virtual_fields.js +58 -0
  338. package/dist/migrations/20260429T102322_catalog_product_type_and_virtual_fields.js.map +1 -0
  339. package/dist/migrations/20260429T111839_catalog_gallery_items_and_labels.d.ts +22 -0
  340. package/dist/migrations/20260429T111839_catalog_gallery_items_and_labels.d.ts.map +1 -0
  341. package/dist/migrations/20260429T111839_catalog_gallery_items_and_labels.js +66 -0
  342. package/dist/migrations/20260429T111839_catalog_gallery_items_and_labels.js.map +1 -0
  343. package/dist/migrations/20260429T112543_catalog_product_attachments.d.ts +18 -0
  344. package/dist/migrations/20260429T112543_catalog_product_attachments.d.ts.map +1 -0
  345. package/dist/migrations/20260429T112543_catalog_product_attachments.js +73 -0
  346. package/dist/migrations/20260429T112543_catalog_product_attachments.js.map +1 -0
  347. package/dist/migrations/20260429T123726_catalog_product_links.d.ts +21 -0
  348. package/dist/migrations/20260429T123726_catalog_product_links.d.ts.map +1 -0
  349. package/dist/migrations/20260429T123726_catalog_product_links.js +48 -0
  350. package/dist/migrations/20260429T123726_catalog_product_links.js.map +1 -0
  351. package/dist/migrations/20260429T130803_catalog_grouped_and_bundle.d.ts +23 -0
  352. package/dist/migrations/20260429T130803_catalog_grouped_and_bundle.d.ts.map +1 -0
  353. package/dist/migrations/20260429T130803_catalog_grouped_and_bundle.js +94 -0
  354. package/dist/migrations/20260429T130803_catalog_grouped_and_bundle.js.map +1 -0
  355. package/dist/migrations/20260501T185835_catalog_product_attribute_is_comparable.d.ts +24 -0
  356. package/dist/migrations/20260501T185835_catalog_product_attribute_is_comparable.d.ts.map +1 -0
  357. package/dist/migrations/20260501T185835_catalog_product_attribute_is_comparable.js +31 -0
  358. package/dist/migrations/20260501T185835_catalog_product_attribute_is_comparable.js.map +1 -0
  359. package/dist/migrations/20260505T060113_catalog_attribute_options_and_flags.d.ts +31 -0
  360. package/dist/migrations/20260505T060113_catalog_attribute_options_and_flags.d.ts.map +1 -0
  361. package/dist/migrations/20260505T060113_catalog_attribute_options_and_flags.js +133 -0
  362. package/dist/migrations/20260505T060113_catalog_attribute_options_and_flags.js.map +1 -0
  363. package/dist/migrations/20260515T082629_catalog_attribute_mass_editable.d.ts +16 -0
  364. package/dist/migrations/20260515T082629_catalog_attribute_mass_editable.d.ts.map +1 -0
  365. package/dist/migrations/20260515T082629_catalog_attribute_mass_editable.js +23 -0
  366. package/dist/migrations/20260515T082629_catalog_attribute_mass_editable.js.map +1 -0
  367. package/dist/migrations/20260526T124736_catalog_product_status_inactive.d.ts +10 -0
  368. package/dist/migrations/20260526T124736_catalog_product_status_inactive.d.ts.map +1 -0
  369. package/dist/migrations/20260526T124736_catalog_product_status_inactive.js +22 -0
  370. package/dist/migrations/20260526T124736_catalog_product_status_inactive.js.map +1 -0
  371. package/dist/migrations/20260611T140346_catalog_product_value_overrides_init.d.ts +38 -0
  372. package/dist/migrations/20260611T140346_catalog_product_value_overrides_init.d.ts.map +1 -0
  373. package/dist/migrations/20260611T140346_catalog_product_value_overrides_init.js +98 -0
  374. package/dist/migrations/20260611T140346_catalog_product_value_overrides_init.js.map +1 -0
  375. package/dist/migrations/20260611T140400_catalog_attribute_quick_searchable.d.ts +13 -0
  376. package/dist/migrations/20260611T140400_catalog_attribute_quick_searchable.d.ts.map +1 -0
  377. package/dist/migrations/20260611T140400_catalog_attribute_quick_searchable.js +17 -0
  378. package/dist/migrations/20260611T140400_catalog_attribute_quick_searchable.js.map +1 -0
  379. package/dist/migrations/20260611T140407_catalog_bulk_operations.d.ts +16 -0
  380. package/dist/migrations/20260611T140407_catalog_bulk_operations.d.ts.map +1 -0
  381. package/dist/migrations/20260611T140407_catalog_bulk_operations.js +42 -0
  382. package/dist/migrations/20260611T140407_catalog_bulk_operations.js.map +1 -0
  383. package/dist/migrations/20260611T140408_catalog_bulk_operation_logs.d.ts +14 -0
  384. package/dist/migrations/20260611T140408_catalog_bulk_operation_logs.d.ts.map +1 -0
  385. package/dist/migrations/20260611T140408_catalog_bulk_operation_logs.js +18 -0
  386. package/dist/migrations/20260611T140408_catalog_bulk_operation_logs.js.map +1 -0
  387. package/dist/migrations/20260611T140412_catalog_product_packaging_units.d.ts +11 -0
  388. package/dist/migrations/20260611T140412_catalog_product_packaging_units.d.ts.map +1 -0
  389. package/dist/migrations/20260611T140412_catalog_product_packaging_units.js +29 -0
  390. package/dist/migrations/20260611T140412_catalog_product_packaging_units.js.map +1 -0
  391. package/dist/migrations/20260718T060659_catalog_bulk_operation_revert_state.d.ts +23 -0
  392. package/dist/migrations/20260718T060659_catalog_bulk_operation_revert_state.d.ts.map +1 -0
  393. package/dist/migrations/20260718T060659_catalog_bulk_operation_revert_state.js +35 -0
  394. package/dist/migrations/20260718T060659_catalog_bulk_operation_revert_state.js.map +1 -0
  395. package/dist/migrations/20260718T200343_catalog_category_custom_field_values.d.ts +12 -0
  396. package/dist/migrations/20260718T200343_catalog_category_custom_field_values.d.ts.map +1 -0
  397. package/dist/migrations/20260718T200343_catalog_category_custom_field_values.js +16 -0
  398. package/dist/migrations/20260718T200343_catalog_category_custom_field_values.js.map +1 -0
  399. package/dist/migrations/20260723T230401_catalog_attributes_on_custom_fields.d.ts +32 -0
  400. package/dist/migrations/20260723T230401_catalog_attributes_on_custom_fields.d.ts.map +1 -0
  401. package/dist/migrations/20260723T230401_catalog_attributes_on_custom_fields.js +286 -0
  402. package/dist/migrations/20260723T230401_catalog_attributes_on_custom_fields.js.map +1 -0
  403. package/dist/migrations/20260804T152604_catalog_widen_product_sku.d.ts +36 -0
  404. package/dist/migrations/20260804T152604_catalog_widen_product_sku.d.ts.map +1 -0
  405. package/dist/migrations/20260804T152604_catalog_widen_product_sku.js +63 -0
  406. package/dist/migrations/20260804T152604_catalog_widen_product_sku.js.map +1 -0
  407. package/dist/migrations/20260804T160244_catalog_category_activation.d.ts +18 -0
  408. package/dist/migrations/20260804T160244_catalog_category_activation.d.ts.map +1 -0
  409. package/dist/migrations/20260804T160244_catalog_category_activation.js +22 -0
  410. package/dist/migrations/20260804T160244_catalog_category_activation.js.map +1 -0
  411. package/dist/migrations/20260912T094557_catalog_sales_channel_products.d.ts +27 -0
  412. package/dist/migrations/20260912T094557_catalog_sales_channel_products.d.ts.map +1 -0
  413. package/dist/migrations/20260912T094557_catalog_sales_channel_products.js +44 -0
  414. package/dist/migrations/20260912T094557_catalog_sales_channel_products.js.map +1 -0
  415. package/dist/migrations/20260912T094623_catalog_sales_channel_categories.d.ts +27 -0
  416. package/dist/migrations/20260912T094623_catalog_sales_channel_categories.d.ts.map +1 -0
  417. package/dist/migrations/20260912T094623_catalog_sales_channel_categories.js +44 -0
  418. package/dist/migrations/20260912T094623_catalog_sales_channel_categories.js.map +1 -0
  419. package/dist/migrations/20260925T125527_catalog_inventory_columns.d.ts +36 -0
  420. package/dist/migrations/20260925T125527_catalog_inventory_columns.d.ts.map +1 -0
  421. package/dist/migrations/20260925T125527_catalog_inventory_columns.js +87 -0
  422. package/dist/migrations/20260925T125527_catalog_inventory_columns.js.map +1 -0
  423. package/dist/migrations/index.d.ts +55 -0
  424. package/dist/migrations/index.d.ts.map +1 -0
  425. package/dist/migrations/index.js +80 -0
  426. package/dist/migrations/index.js.map +1 -0
  427. package/dist/ports/index.d.ts +96 -0
  428. package/dist/ports/index.d.ts.map +1 -0
  429. package/dist/ports/index.js +2 -0
  430. package/dist/ports/index.js.map +1 -0
  431. package/docs/catalog/attachments.md +69 -0
  432. package/docs/catalog/attribute-sets.md +63 -0
  433. package/docs/catalog/attributes.md +244 -0
  434. package/docs/catalog/composite-products.md +115 -0
  435. package/docs/catalog/gallery-and-labels.md +73 -0
  436. package/docs/catalog/packaging-units.md +67 -0
  437. package/docs/catalog/per-channel-per-language-overrides.md +234 -0
  438. package/docs/catalog/product-links.md +79 -0
  439. package/docs/catalog.md +207 -0
  440. package/i18n/en.json +649 -0
  441. package/i18n/pl.json +649 -0
  442. package/package.json +109 -0
  443. package/tailwind.css +14 -0
@@ -0,0 +1,510 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { BULK_OPERATION_TYPES, } from '@endora-commerce/contracts';
3
+ import { effectiveState } from '@endora-commerce/platform/kernel';
4
+ import { rethrowIfModuleDisabled } from '@endora-commerce/platform/kernel';
5
+ import { applyUndo } from '@endora-commerce/platform/commands';
6
+ import { Product } from '../entities/product.entity.js';
7
+ import { BulkOperation, } from '../entities/bulk-operation.entity.js';
8
+ /**
9
+ * BulkOperationService — queued product bulk-edit.
10
+ *
11
+ * Owns the lifecycle of {@link BulkOperation} rows:
12
+ * - `create()` persists a `pending` row and enqueues it (via the injected
13
+ * `onEnqueued` producer) onto the durable BullMQ queue — it never
14
+ * inline-executes the job (Constitution Principle X).
15
+ * - `processById()` is the consumer entry point invoked by the BullMQ
16
+ * worker: it claims the row atomically (`pending → running`) and applies
17
+ * it through {@link CatalogBulkUpdateService} with live progress persisted
18
+ * on the row. The conditional claim makes it idempotent under BullMQ
19
+ * redelivery / retries and safe at N ≥ 2 worker instances.
20
+ * - `processPending()` drains every `pending` row in-process; it is kept for
21
+ * manual scripts / tests only — the deployed path is the queue worker.
22
+ * - On completion / failure the requester is notified twice: an
23
+ * in-app bell notification and an email.
24
+ * - `list()` / `get()` back the "Bulk actions" admin page.
25
+ */
26
+ /** Per-product outcomes are capped on the row so a huge run can't bloat it. */
27
+ const MAX_PERSISTED_RESULTS = 1000;
28
+ /**
29
+ * Wraps the gated port in the presence decision, so absence is *decided* rather
30
+ * than caught (D-60; Constitution XVII).
31
+ *
32
+ * A function rather than an object literal at the composition site on purpose:
33
+ * `check-port-catches.ts` follows the port **through the value**, and an object
34
+ * literal is where that trail deliberately stops.
35
+ */
36
+ export function presenceAwareBulkRecorder(adminNotifications) {
37
+ return {
38
+ async record(input) {
39
+ // First, and outside any `try`: a closed gate throws rather than
40
+ // answering, so asking after the call is asking too late.
41
+ if (!effectiveState.isPresent('admin_notifications'))
42
+ return 'not-present';
43
+ await adminNotifications.record(input);
44
+ return 'recorded';
45
+ },
46
+ };
47
+ }
48
+ export class BulkOperationService {
49
+ emFactory;
50
+ bulkUpdateService;
51
+ deps;
52
+ commandBus;
53
+ /** Single-flight guard so overlapping sweep ticks don't double-process. */
54
+ draining = false;
55
+ constructor(emFactory, bulkUpdateService, deps = {},
56
+ /**
57
+ * Feature 054 — when injected, product bulk edits capture per-product revert
58
+ * state and expose an audited, conflict-aware undo (US2). Optional so bus-less
59
+ * constructions (some tests) keep the pre-054 behavior.
60
+ */
61
+ commandBus) {
62
+ this.emFactory = emFactory;
63
+ this.bulkUpdateService = bulkUpdateService;
64
+ this.deps = deps;
65
+ this.commandBus = commandBus;
66
+ }
67
+ async create(input) {
68
+ // command-coverage-ignore: catalog_bulk_operations row bookkeeping (queue
69
+ // status / progress counters); the actual product mutations are audited by
70
+ // updateProduct. The operation record itself is not a domain-audit target.
71
+ const em = this.emFactory();
72
+ const op = new BulkOperation();
73
+ op.type = input.type ?? 'product_bulk_update';
74
+ op.status = 'pending';
75
+ op.requestedByAdminUserId = input.requestedByAdminUserId;
76
+ op.total = input.payload.productIds.length;
77
+ op.payload = input.payload;
78
+ op.logs = [
79
+ logEntry('info', op.type === BULK_OPERATION_TYPES.SEARCH_REINDEX
80
+ ? 'Operacja przeindeksowania wyszukiwarki utworzona i dodana do kolejki.'
81
+ : `Operacja utworzona i dodana do kolejki (${op.total} elementów).`),
82
+ ];
83
+ await em.persistAndFlush(op);
84
+ // Producer side (Principle X): enqueue and return. Never block the HTTP
85
+ // response on actual processing. Enqueue errors are non-fatal — the row
86
+ // stays `pending` and the worker's boot reconciliation re-enqueues it.
87
+ try {
88
+ await this.deps.onEnqueued?.(op.id);
89
+ }
90
+ catch {
91
+ /* enqueue is best-effort; reconciliation is the safety net */
92
+ }
93
+ return serialize(op);
94
+ }
95
+ /**
96
+ * Consumer entry point invoked by the BullMQ worker for one queued
97
+ * operation. Atomically claims the row (`pending → running`); if the claim
98
+ * affects no row the operation was already taken or finished, so this is a
99
+ * no-op — making the handler idempotent under redelivery/retries and safe at
100
+ * N ≥ 2 worker instances.
101
+ */
102
+ async processById(operationId) {
103
+ // command-coverage-ignore: catalog_bulk_operations row bookkeeping (queue
104
+ // status / progress counters); the actual product mutations are audited by
105
+ // updateProduct. The operation record itself is not a domain-audit target.
106
+ const em = this.emFactory();
107
+ const affected = await em.nativeUpdate(BulkOperation, { id: operationId, status: 'pending' }, { status: 'running', startedAt: new Date() });
108
+ if (affected === 0)
109
+ return;
110
+ await this.processOne(operationId);
111
+ }
112
+ /**
113
+ * Ids of every operation still `pending`. Used by the worker at boot to
114
+ * re-enqueue rows that were created while no producer/queue was reachable
115
+ * (e.g. an enqueue failure, or a row predating this deployment).
116
+ */
117
+ async findPendingIds() {
118
+ const em = this.emFactory();
119
+ const rows = await em.find(BulkOperation, { status: 'pending' }, { fields: ['id'], orderBy: { createdAt: 'asc' } });
120
+ return rows.map((r) => r.id);
121
+ }
122
+ async list(input = {}) {
123
+ const em = this.emFactory();
124
+ const where = input.status && input.status.length > 0 ? { status: { $in: input.status } } : {};
125
+ const limit = Math.min(Math.max(input.limit ?? 25, 1), 100);
126
+ const offset = Math.max(input.offset ?? 0, 0);
127
+ const [rows, total] = await em.findAndCount(BulkOperation, where, {
128
+ orderBy: { createdAt: 'desc' },
129
+ limit,
130
+ offset,
131
+ });
132
+ return { items: rows.map(serialize), total };
133
+ }
134
+ async get(id) {
135
+ const em = this.emFactory();
136
+ const op = await em.findOne(BulkOperation, { id });
137
+ return op ? serialize(op) : null;
138
+ }
139
+ /**
140
+ * Drain every `pending` operation. Safe to call repeatedly and
141
+ * concurrently — the single-flight guard ensures one drain at a time.
142
+ */
143
+ async processPending() {
144
+ if (this.draining)
145
+ return { processed: 0 };
146
+ this.draining = true;
147
+ let processed = 0;
148
+ try {
149
+ for (;;) {
150
+ const next = await this.claimNextPending();
151
+ if (!next)
152
+ break;
153
+ await this.processOne(next);
154
+ processed += 1;
155
+ }
156
+ }
157
+ finally {
158
+ this.draining = false;
159
+ }
160
+ return { processed };
161
+ }
162
+ /**
163
+ * Atomically flip the oldest `pending` row to `running` and return its
164
+ * id. The conditional UPDATE means even if two drains race past the
165
+ * in-process guard (e.g. across worker restarts) only one wins a row.
166
+ */
167
+ async claimNextPending() {
168
+ // command-coverage-ignore: catalog_bulk_operations row bookkeeping (queue
169
+ // status / progress counters); the actual product mutations are audited by
170
+ // updateProduct. The operation record itself is not a domain-audit target.
171
+ const em = this.emFactory();
172
+ const candidate = await em.findOne(BulkOperation, { status: 'pending' }, { orderBy: { createdAt: 'asc' } });
173
+ if (!candidate)
174
+ return null;
175
+ const affected = await em.nativeUpdate(BulkOperation, { id: candidate.id, status: 'pending' }, { status: 'running', startedAt: new Date() });
176
+ if (affected === 0) {
177
+ // Lost the race — try again on the next loop iteration.
178
+ return this.claimNextPending();
179
+ }
180
+ return candidate.id;
181
+ }
182
+ async processOne(id) {
183
+ // command-coverage-ignore: catalog_bulk_operations row bookkeeping (queue
184
+ // status / progress counters); the actual product mutations are audited by
185
+ // updateProduct. The operation record itself is not a domain-audit target.
186
+ const em = this.emFactory();
187
+ const op = await em.findOne(BulkOperation, { id });
188
+ if (!op)
189
+ return;
190
+ const logs = Array.isArray(op.logs) ? [...op.logs] : [];
191
+ logs.push(logEntry('info', `Rozpoczęto przetwarzanie operacji (${op.total} elementów).`));
192
+ if (op.type === BULK_OPERATION_TYPES.SEARCH_REINDEX) {
193
+ await this.processReindex(op, logs);
194
+ return;
195
+ }
196
+ const req = {
197
+ productIds: op.payload.productIds,
198
+ fields: op.payload.fields,
199
+ };
200
+ // Feature 054 (US2) — capture per-product before-state for undo, but only
201
+ // when the edit touches revertible direct columns (never the category
202
+ // bridge). Read BEFORE the mutation so the snapshot is the true pre-state.
203
+ const revertKeys = this.commandBus ? revertibleFieldKeys(op.payload.fields) : null;
204
+ const beforeByProduct = revertKeys && revertKeys.length > 0
205
+ ? await this.#snapshotProductFields(em, op.payload.productIds, revertKeys)
206
+ : null;
207
+ try {
208
+ const result = await this.bulkUpdateService.bulkUpdate(req, { actorAdminUserId: op.requestedByAdminUserId }, {
209
+ skipBatchLimit: true,
210
+ onProgress: async (p) => {
211
+ await em.nativeUpdate(BulkOperation, { id }, {
212
+ processed: p.processed,
213
+ succeeded: p.succeeded,
214
+ skipped: p.skipped,
215
+ failed: p.failed,
216
+ });
217
+ },
218
+ });
219
+ logs.push(logEntry('info', `Zakończono: ${result.summary.succeeded} z powodzeniem, ${result.summary.skipped} pominięto, ${result.summary.failed} z błędem (łącznie ${result.summary.total}).`));
220
+ if (result.summary.failed > 0) {
221
+ logs.push(logEntry('warn', `${result.summary.failed} elementów zakończyło się błędem — szczegóły w statusie pojedynczych elementów.`));
222
+ }
223
+ // Build revert state from the products that actually succeeded, reading
224
+ // their post-state so undo can detect later changes (research §R5).
225
+ let revertState = null;
226
+ if (revertKeys && revertKeys.length > 0 && beforeByProduct) {
227
+ const succeededIds = result.results
228
+ .filter((r) => r.status === 'succeeded')
229
+ .map((r) => r.productId)
230
+ .filter((pid) => beforeByProduct.has(pid));
231
+ const afterByProduct = await this.#snapshotProductFields(em, succeededIds, revertKeys);
232
+ revertState = succeededIds.map((pid) => ({
233
+ recordId: pid,
234
+ before: beforeByProduct.get(pid),
235
+ after: afterByProduct.get(pid) ?? {},
236
+ }));
237
+ }
238
+ await em.nativeUpdate(BulkOperation, { id }, {
239
+ status: 'completed',
240
+ processed: result.summary.total,
241
+ succeeded: result.summary.succeeded,
242
+ skipped: result.summary.skipped,
243
+ failed: result.summary.failed,
244
+ results: result.results.slice(0, MAX_PERSISTED_RESULTS),
245
+ logs,
246
+ finishedAt: new Date(),
247
+ ...(revertState && revertState.length > 0
248
+ ? { reversible: true, revertState }
249
+ : {}),
250
+ });
251
+ await this.notify(op, 'completed', result.summary);
252
+ }
253
+ catch (err) {
254
+ const message = err instanceof Error ? err.message : String(err);
255
+ logs.push(logEntry('error', `Operacja nie powiodła się: ${message}`));
256
+ await em.nativeUpdate(BulkOperation, { id }, { status: 'failed', error: message, logs, finishedAt: new Date() });
257
+ await this.notify(op, 'failed', null, message);
258
+ }
259
+ }
260
+ /**
261
+ * Runs a `search_reindex` operation: a full Meilisearch reindex (the
262
+ * `search:reindex` CLI equivalent). Counts every reindexed document as
263
+ * both processed and succeeded; failure surfaces on the row + notifications.
264
+ */
265
+ async processReindex(op, logs = []) {
266
+ // command-coverage-ignore: catalog_bulk_operations row bookkeeping (queue
267
+ // status / progress counters); the actual product mutations are audited by
268
+ // updateProduct. The operation record itself is not a domain-audit target.
269
+ const em = this.emFactory();
270
+ if (!this.deps.reindexRunner) {
271
+ const message = 'Search reindex handler is not configured.';
272
+ logs.push(logEntry('error', `Operacja nie powiodła się: ${message}`));
273
+ await em.nativeUpdate(BulkOperation, { id: op.id }, { status: 'failed', error: message, logs, finishedAt: new Date() });
274
+ await this.notify(op, 'failed', null, message);
275
+ return;
276
+ }
277
+ try {
278
+ const { documentCount } = await this.deps.reindexRunner();
279
+ logs.push(logEntry('info', `Przeindeksowano ${documentCount} dokumentów we wszystkich indeksach.`));
280
+ await em.nativeUpdate(BulkOperation, { id: op.id }, {
281
+ status: 'completed',
282
+ total: documentCount,
283
+ processed: documentCount,
284
+ succeeded: documentCount,
285
+ skipped: 0,
286
+ failed: 0,
287
+ logs,
288
+ finishedAt: new Date(),
289
+ });
290
+ await this.notify(op, 'completed', {
291
+ succeeded: documentCount,
292
+ skipped: 0,
293
+ failed: 0,
294
+ total: documentCount,
295
+ });
296
+ }
297
+ catch (err) {
298
+ const message = err instanceof Error ? err.message : String(err);
299
+ logs.push(logEntry('error', `Operacja nie powiodła się: ${message}`));
300
+ await em.nativeUpdate(BulkOperation, { id: op.id }, { status: 'failed', error: message, logs, finishedAt: new Date() });
301
+ await this.notify(op, 'failed', null, message);
302
+ }
303
+ }
304
+ async notify(op, status, summary, error) {
305
+ const admin = await this.deps.adminUsers?.findById(op.requestedByAdminUserId);
306
+ const succeeded = summary?.succeeded ?? 0;
307
+ const total = summary?.total ?? op.total;
308
+ const isReindex = op.type === BULK_OPERATION_TYPES.SEARCH_REINDEX;
309
+ const title = isReindex
310
+ ? status === 'completed'
311
+ ? `Search reindex finished — ${total} documents indexed`
312
+ : 'Search reindex failed'
313
+ : status === 'completed'
314
+ ? `Bulk edit finished — ${succeeded}/${total} updated`
315
+ : 'Bulk edit failed';
316
+ const body = isReindex
317
+ ? status === 'completed'
318
+ ? `The search index was rebuilt: ${total} documents indexed.`
319
+ : `The search reindex could not be completed: ${error ?? 'unknown error'}.`
320
+ : status === 'completed'
321
+ ? `${total} products processed: ${succeeded} succeeded, ${summary?.skipped ?? 0} skipped, ${summary?.failed ?? 0} failed.`
322
+ : `The bulk edit of ${op.total} products could not be completed: ${error ?? 'unknown error'}.`;
323
+ try {
324
+ // The outcome is read rather than discarded: `not-present` is the
325
+ // operator having switched `admin_notifications` off, which is their
326
+ // choice and not a failure, and it used to be indistinguishable from a
327
+ // failed write inside this `catch` (D-60).
328
+ await this.deps.notificationService?.record({
329
+ audience: 'admin_user',
330
+ targetAdminUserId: op.requestedByAdminUserId,
331
+ kind: `catalog.bulk_operation.${status}`,
332
+ subjectType: 'bulk_operation',
333
+ subjectId: op.id,
334
+ title,
335
+ body,
336
+ linkPath: '/catalog/bulk-operations',
337
+ });
338
+ }
339
+ catch (err) {
340
+ // Narrow, and correct: the bell is written when the operation has already
341
+ // finished and its row carries the outcome, so a failed write must not
342
+ // fail a job whose work is done. Presence is decided by the recorder
343
+ // before the port is reached, so what is left here is a failed write.
344
+ rethrowIfModuleDisabled(err);
345
+ /* notification is best-effort */
346
+ }
347
+ if (this.deps.mailer && admin?.email) {
348
+ try {
349
+ const outcome = await this.deps.mailer.send({
350
+ messageId: `bulk-op-${op.id}-${status}`,
351
+ to: admin.email,
352
+ subject: title,
353
+ text: `${body}\n\nView the bulk actions page in the admin panel for details.`,
354
+ kind: `catalog.bulk_operation.${status}`,
355
+ meta: { bulkOperationId: op.id, status },
356
+ });
357
+ if (outcome.status !== 'sent') {
358
+ // The products are already written; this only tells the operator it
359
+ // finished. Named rather than silent, and durable in D-59's record.
360
+ console.warn('[catalog] the bulk-operation e-mail was not sent', {
361
+ bulkOperationId: op.id,
362
+ reason: outcome.reason,
363
+ });
364
+ }
365
+ }
366
+ catch {
367
+ /* email is best-effort */
368
+ }
369
+ }
370
+ }
371
+ // ---- Feature 054 (US2) — undo -----------------------------------------
372
+ /**
373
+ * Undo a reversible bulk edit: restore every affected product whose current
374
+ * state still matches the operation's captured after-state; refuse (report,
375
+ * never clobber) any product changed since. Runs as an audited `bulk.undo`
376
+ * Command and is idempotent-safe on re-invocation (FR-006/FR-007/FR-014).
377
+ */
378
+ async undo(operationId) {
379
+ const em = this.emFactory();
380
+ const op = await em.findOne(BulkOperation, { id: operationId });
381
+ if (!op)
382
+ return { ok: false, code: 'NOT_FOUND' };
383
+ if (op.status !== 'completed' || !op.reversible || !op.revertState || op.revertState.length === 0) {
384
+ return { ok: false, code: 'NOT_REVERSIBLE' };
385
+ }
386
+ if (op.undoStatus === 'reverted')
387
+ return { ok: false, code: 'ALREADY_REVERTED' };
388
+ if (!this.commandBus)
389
+ return { ok: false, code: 'NOT_REVERSIBLE' };
390
+ const records = op.revertState.map((r) => ({
391
+ recordId: r.recordId,
392
+ before: r.before,
393
+ after: r.after,
394
+ }));
395
+ return this.commandBus.run(this.#undoCommand(operationId, records));
396
+ }
397
+ #undoCommand(operationId, records) {
398
+ return {
399
+ action: 'product.bulk_update.undo',
400
+ objectType: 'bulk_operation',
401
+ objectId: operationId,
402
+ run: async ({ em }) => {
403
+ const op = await em.findOne(BulkOperation, { id: operationId });
404
+ if (!op || op.undoStatus === 'reverted') {
405
+ return {
406
+ result: { ok: true, reverted: [], conflicts: [], undoStatus: 'reverted' },
407
+ skipAudit: true,
408
+ };
409
+ }
410
+ const res = await applyUndo(em, records, {
411
+ readCurrent: async (tem, rec) => {
412
+ const p = await tem.findOne(Product, { id: rec.recordId });
413
+ return p ? pickProductFields(p, Object.keys(rec.after)) : null;
414
+ },
415
+ restore: async (tem, rec) => {
416
+ const p = await tem.findOne(Product, { id: rec.recordId });
417
+ if (!p)
418
+ return;
419
+ tem.assign(p, rec.before);
420
+ tem.persist(p);
421
+ },
422
+ });
423
+ op.undoStatus = res.undoStatus === 'reverted' ? 'reverted' : 'partially_reverted';
424
+ op.undoneAt = new Date();
425
+ op.undoOperationId = randomUUID();
426
+ em.persist(op);
427
+ return {
428
+ result: { ok: true, ...res },
429
+ after: { reverted: res.reverted.length, conflicts: res.conflicts.length },
430
+ };
431
+ },
432
+ };
433
+ }
434
+ /** Read `productIds` and pick each product's values for `keys`. */
435
+ async #snapshotProductFields(em, productIds, keys) {
436
+ const out = new Map();
437
+ if (productIds.length === 0)
438
+ return out;
439
+ const products = await em.find(Product, { id: { $in: [...productIds] } });
440
+ for (const p of products) {
441
+ out.set(p.id, pickProductFields(p, keys));
442
+ }
443
+ return out;
444
+ }
445
+ }
446
+ /**
447
+ * Field keys of a bulk edit that can be undone by restoring direct product
448
+ * columns. Returns `[]` (⇒ not reversible) when the edit is empty or touches a
449
+ * non-revertible field (the category bridge) — all-or-nothing, never partial.
450
+ */
451
+ const NON_REVERTIBLE_BULK_FIELDS = new Set(['categoryIds']);
452
+ function revertibleFieldKeys(fields) {
453
+ const keys = Object.keys(fields);
454
+ if (keys.length === 0)
455
+ return [];
456
+ if (keys.some((k) => NON_REVERTIBLE_BULK_FIELDS.has(k)))
457
+ return [];
458
+ const set = new Set(keys);
459
+ // `status` changes also flip `archivedAt` in updateProduct — restore both.
460
+ if (set.has('status'))
461
+ set.add('archivedAt');
462
+ return [...set];
463
+ }
464
+ /** Pick a plain, JSON-cloned snapshot of a product's `keys` for revert state. */
465
+ function pickProductFields(product, keys) {
466
+ const src = product;
467
+ const out = {};
468
+ for (const key of keys) {
469
+ const v = src[key];
470
+ out[key] = v === undefined ? null : JSON.parse(JSON.stringify(v ?? null));
471
+ }
472
+ return out;
473
+ }
474
+ function logEntry(level, message) {
475
+ return { ts: new Date().toISOString(), level, message };
476
+ }
477
+ function touchedFieldsOf(payload) {
478
+ const fields = payload.fields ?? {};
479
+ const keys = Object.keys(fields).filter((k) => k !== 'attributeValues');
480
+ if (fields['attributeValues'] && typeof fields['attributeValues'] === 'object') {
481
+ for (const attrKey of Object.keys(fields['attributeValues'])) {
482
+ keys.push(`attribute:${attrKey}`);
483
+ }
484
+ }
485
+ return keys;
486
+ }
487
+ function serialize(op) {
488
+ return {
489
+ id: op.id,
490
+ type: op.type,
491
+ status: op.status,
492
+ requestedByAdminUserId: op.requestedByAdminUserId,
493
+ total: op.total,
494
+ processed: op.processed,
495
+ succeeded: op.succeeded,
496
+ skipped: op.skipped,
497
+ failed: op.failed,
498
+ touchedFields: touchedFieldsOf(op.payload),
499
+ results: op.results ?? null,
500
+ logs: op.logs ?? null,
501
+ error: op.error ?? null,
502
+ createdAt: op.createdAt.toISOString(),
503
+ startedAt: op.startedAt ? op.startedAt.toISOString() : null,
504
+ finishedAt: op.finishedAt ? op.finishedAt.toISOString() : null,
505
+ reversible: op.reversible,
506
+ undoStatus: op.undoStatus,
507
+ undoneAt: op.undoneAt ? op.undoneAt.toISOString() : null,
508
+ };
509
+ }
510
+ //# sourceMappingURL=bulk-operation.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulk-operation.service.js","sourceRoot":"","sources":["../../../src/backend/services/bulk-operation.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import type { CommandBus } from '@endora-commerce/platform/commands';
3
+ /**
4
+ * BundleService — admin CRUD for bundle slots + their options, plus the
5
+ * pure-compute `validateConfiguration` used by the public storefront
6
+ * endpoint (feature 002 US5, T129).
7
+ *
8
+ * Same composite-nesting guard as GroupedService: option products MUST
9
+ * NOT be `type='grouped'` or `type='bundle'` (research R-8).
10
+ */
11
+ export interface BundleSlotRow {
12
+ id: string;
13
+ parentProductId: string;
14
+ name: Record<string, string>;
15
+ minQuantity: number;
16
+ maxQuantity: number;
17
+ position: number;
18
+ options: BundleSlotOptionRow[];
19
+ }
20
+ export interface BundleSlotOptionRow {
21
+ id: string;
22
+ slotId: string;
23
+ optionProductId: string;
24
+ defaultQuantity: number;
25
+ position: number;
26
+ }
27
+ export interface ConfigurationSelection {
28
+ slotId: string;
29
+ optionId: string;
30
+ quantity: number;
31
+ }
32
+ export interface BundleValidationError {
33
+ code: 'MIN_NOT_MET' | 'MAX_EXCEEDED' | 'UNKNOWN_OPTION';
34
+ slotId?: string;
35
+ message: string;
36
+ }
37
+ export interface BundleValidationResult {
38
+ valid: boolean;
39
+ errors: BundleValidationError[];
40
+ resolvedSelections: Array<{
41
+ slotId: string;
42
+ optionId: string;
43
+ optionProductId: string;
44
+ quantity: number;
45
+ }>;
46
+ }
47
+ export declare class BundleService {
48
+ #private;
49
+ private readonly emFactory;
50
+ /** Feature 054 — audits bundle slot/option writes co-transactionally when provided. */
51
+ private readonly commandBus?;
52
+ constructor(emFactory: () => EntityManager,
53
+ /** Feature 054 — audits bundle slot/option writes co-transactionally when provided. */
54
+ commandBus?: CommandBus | undefined);
55
+ listSlots(parentProductId: string): Promise<BundleSlotRow[]>;
56
+ createSlot(parentProductId: string, input: {
57
+ name: Record<string, string>;
58
+ minQuantity?: number | undefined;
59
+ maxQuantity: number;
60
+ position?: number | undefined;
61
+ }): Promise<BundleSlotRow>;
62
+ updateSlot(parentProductId: string, slotId: string, input: {
63
+ name?: Record<string, string> | undefined;
64
+ minQuantity?: number | undefined;
65
+ maxQuantity?: number | undefined;
66
+ position?: number | undefined;
67
+ }): Promise<BundleSlotRow>;
68
+ deleteSlot(parentProductId: string, slotId: string): Promise<void>;
69
+ addOption(parentProductId: string, slotId: string, input: {
70
+ optionProductId: string;
71
+ defaultQuantity?: number | undefined;
72
+ position?: number | undefined;
73
+ }): Promise<BundleSlotOptionRow>;
74
+ removeOption(parentProductId: string, slotId: string, optionId: string): Promise<void>;
75
+ /**
76
+ * Pure-compute validation of a buyer's bundle configuration. Returns a
77
+ * structured result rather than throwing — the storefront wants the
78
+ * whole error list per-slot so it can highlight every offending row.
79
+ *
80
+ * Throws HttpError 400 only when the parent product is not a bundle
81
+ * (the call doesn't make sense in that case).
82
+ */
83
+ validateConfiguration(parentProductId: string, selections: ConfigurationSelection[]): Promise<BundleValidationResult>;
84
+ private assertBundleParent;
85
+ private toOptionRow;
86
+ }
87
+ //# sourceMappingURL=bundle.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.service.d.ts","sourceRoot":"","sources":["../../../src/backend/services/bundle.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAI3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAKrE;;;;;;;GAOG;AAEH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,aAAa,GAAG,cAAc,GAAG,gBAAgB,CAAC;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,kBAAkB,EAAE,KAAK,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,eAAe,EAAE,MAAM,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ;AAED,qBAAa,aAAa;;IAEtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,uFAAuF;IACvF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;gBAFX,SAAS,EAAE,MAAM,aAAa;IAC/C,uFAAuF;IACtE,UAAU,CAAC,EAAE,UAAU,YAAA;IAsBpC,SAAS,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAgC5D,UAAU,CACd,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACjC,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC/B,GACA,OAAO,CAAC,aAAa,CAAC;IA4CnB,UAAU,CACd,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;QAC1C,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACjC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC/B,GACA,OAAO,CAAC,aAAa,CAAC;IA8CnB,UAAU,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlE,SAAS,CACb,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;QACL,eAAe,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACrC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC/B,GACA,OAAO,CAAC,mBAAmB,CAAC;IA+DzB,YAAY,CAChB,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAiBhB;;;;;;;OAOG;IACG,qBAAqB,CACzB,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,sBAAsB,EAAE,GACnC,OAAO,CAAC,sBAAsB,CAAC;YAgEpB,kBAAkB;IAsBhC,OAAO,CAAC,WAAW;CASpB"}