@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,642 @@
1
+ import { z } from 'zod';
2
+ import { ERROR_CODES } from '@endora-commerce/contracts';
3
+ import { HttpError } from '@endora-commerce/platform/http';
4
+ import { StorefrontRevalidator } from '@endora-commerce/platform/http';
5
+ import { lazyPort } from '@endora-commerce/platform/kernel';
6
+ import { effectiveState } from '@endora-commerce/platform/kernel';
7
+ import { AttachmentType } from './entities/attachment-type.entity.js';
8
+ import { AttributeSetAttribute } from './entities/attribute-set-attribute.entity.js';
9
+ import { AttributeSet } from './entities/attribute-set.entity.js';
10
+ import { BulkOperation } from './entities/bulk-operation.entity.js';
11
+ import { BundleSlotOption } from './entities/bundle-slot-option.entity.js';
12
+ import { BundleSlot } from './entities/bundle-slot.entity.js';
13
+ import { Category } from './entities/category.entity.js';
14
+ import { GalleryItemLabel } from './entities/gallery-item-label.entity.js';
15
+ import { GalleryItem } from './entities/gallery-item.entity.js';
16
+ import { GroupedItem } from './entities/grouped-item.entity.js';
17
+ import { ProductAttachment } from './entities/product-attachment.entity.js';
18
+ import { ProductAttribute } from './entities/product-attribute.entity.js';
19
+ import { ProductEditorPreference } from './entities/product-editor-preference.entity.js';
20
+ import { ProductLink } from './entities/product-link.entity.js';
21
+ import { ProductPackagingUnit } from './entities/product-packaging-unit.entity.js';
22
+ import { ProductValueOverride } from './entities/product-value-override.entity.js';
23
+ import { ProductVariant } from './entities/product-variant.entity.js';
24
+ import { Product } from './entities/product.entity.js';
25
+ import { catalogModule } from './plugin.js';
26
+ import { CatalogAdminService } from './services/catalog-admin.service.js';
27
+ import { CatalogBulkImportService } from './services/catalog-bulk-import.service.js';
28
+ import { CategoryAdminService } from './services/category-admin.service.js';
29
+ import { AttributeSetService } from './services/attribute-set.service.js';
30
+ import { GalleryService } from './services/gallery.service.js';
31
+ import { AttachmentService } from './services/attachment.service.js';
32
+ import { ProductLinkService } from './services/product-link.service.js';
33
+ import { GroupedService } from './services/grouped.service.js';
34
+ import { BundleService } from './services/bundle.service.js';
35
+ import { PackagingUnitService } from './services/packaging-unit.service.js';
36
+ import { CatalogAttributeReadService } from './services/catalog-attribute-read.service.js';
37
+ import { CatalogCategoryReadService } from './services/catalog-category-read.service.js';
38
+ import { CatalogProductFilterService } from './services/catalog-product-filter.service.js';
39
+ import { CatalogProductReadService } from './services/catalog-product-read.service.js';
40
+ import { CatalogQueryService } from './services/catalog-query.service.js';
41
+ import { CatalogQuickSearchService } from './services/catalog-quick-search.service.js';
42
+ import { ProductOverridesService } from './services/product-overrides.service.js';
43
+ import { AttributeValueKeyService } from './services/attribute-value-key.service.js';
44
+ import { createCatalogCategoryWritePort, createCatalogProductWritePort, createCatalogPromoAttributePort, } from './services/catalog-write-ports.js';
45
+ import { registerCatalogAssetReferences } from './services/asset-references.js';
46
+ import { registerCatalogAuditReferences } from './services/audit-references.js';
47
+ import { presenceAwareBulkRecorder } from './services/bulk-operation.service.js';
48
+ import { catalogBulkProgressReader, catalogPromptMutationTools, catalogPromptResolverTools, } from './prompt-tools.js';
49
+ export function registerModule(ctx) {
50
+ /**
51
+ * Feature 120 (FR-015) — the sales-channel membership bridges this module owns.
52
+ *
53
+ * The platform used to hold a map **total** over
54
+ * `ChannelMemberEntityTypeSchema`, naming this module's bridge table from
55
+ * inside the kernel. That is D-52/D-53's prohibition expressed in a contract
56
+ * instead of an import, and it meant a membership call for 'product', 'category' on an
57
+ * instance that never installed this module executed SQL against a relation
58
+ * that is not there (D-226). The module whose migration creates the table is
59
+ * the one that says where it is; a member nothing registers now refuses at
60
+ * the call instead.
61
+ *
62
+ * A **contribution** hook and deliberately **unprobed** (D-62/D-68): a
63
+ * registration is an inert statement about the schema rather than a
64
+ * capability, the rows outlive an operator switching this module off, and
65
+ * probing would make a runtime activation flip require a restart. It is
66
+ * declared first in this module so any later hook of its own that binds a
67
+ * membership finds the bridge already there.
68
+ */
69
+ ctx.onBoot(() => {
70
+ const { salesChannelBridgeRegistry } = ctx.cradle();
71
+ for (const bridge of salesChannelBridges)
72
+ salesChannelBridgeRegistry.register(bridge);
73
+ });
74
+ const cradle = () => ctx.cradle();
75
+ /**
76
+ * The two API-key gates, with the presence probe D-44 requires of a
77
+ * `degrades-without` edge.
78
+ *
79
+ * The manifest withdraws the flip-time refusal on these, so `api_keys` may be
80
+ * absent while these routes are mounted — route *registration* runs whatever
81
+ * any module's effective state is. `requireApiKey` is a gated port, and a
82
+ * closed gate **throws** rather than resolving to `undefined`, so optional
83
+ * chaining defends against nothing here: the probe has to come first.
84
+ *
85
+ * Per request rather than per registration, because the operator flips
86
+ * between the two. The absent answer is the same 401 an unauthenticated
87
+ * caller gets — the door is shut, not broken.
88
+ *
89
+ * Written out twice rather than parameterised by the port name: a computed
90
+ * cradle read is a name `check-port-dependencies.ts` cannot verify, and it
91
+ * refuses the shape rather than guessing at it.
92
+ */
93
+ const apiKeysPresent = () => {
94
+ if (!effectiveState.isPresent('api_keys')) {
95
+ throw new HttpError(401, ERROR_CODES.UNAUTHORIZED, 'API key required.');
96
+ }
97
+ };
98
+ const requireApiKeyGate = (scope) => async (request, reply) => {
99
+ apiKeysPresent();
100
+ return cradle().requireApiKey(scope)(request, reply);
101
+ };
102
+ const requireBoundApiKeyGate = (scope) => async (request, reply) => {
103
+ apiKeysPresent();
104
+ return cradle().requireBoundApiKey(scope)(request, reply);
105
+ };
106
+ /**
107
+ * Issue #185 — the per-warehouse threshold copy product duplication makes.
108
+ *
109
+ * `duplicateProduct` used to run an `insert … select` into
110
+ * `product_warehouse_low_stock_thresholds` on its own `EntityManager`. The
111
+ * table is `inventory`'s, created by `inventory`'s migration, and the
112
+ * statement named no import specifier, asked no gate and left no audit row on
113
+ * that module's side — so the copy went on happening with `inventory`
114
+ * switched off.
115
+ *
116
+ * The same D-44 shape as the two API-key gates above, and for the same
117
+ * reason: this module declares `inventoryProductThresholdWritePort`
118
+ * `degrades-without`, so a closed gate must never be *met*. Presence is
119
+ * decided here, in front of the resolution, and the absent answer travels in
120
+ * the return type rather than through a `catch` that would read a genuine
121
+ * inventory failure as "this deployment has no warehouses".
122
+ */
123
+ const inventoryThresholds = lazyPort(ctx, 'inventoryProductThresholdWritePort');
124
+ const copyWarehouseThresholds = async (input) => {
125
+ if (!effectiveState.isPresent('inventory'))
126
+ return 'not-present';
127
+ return inventoryThresholds.copyProductWarehouseThresholds(input);
128
+ };
129
+ /**
130
+ * The three names a composition root supplied on this module's behalf until
131
+ * `specs/117-instance-bring-up/` Phase 6 (FR-033).
132
+ *
133
+ * Each reaches something this module may not read directly, and each reaches
134
+ * it through a seam that already exists here: two gated ports whose owners
135
+ * this manifest declares `degrades-without`, and two platform registrations.
136
+ * None of the three carried a deployment judgement — the availability closure
137
+ * was `effectiveState.isPresent('inventory')` plus a port, which is literally
138
+ * the shape a module writes for itself.
139
+ */
140
+ ctx.di.register({
141
+ /**
142
+ * The availability band the external catalog namespace decorates a product
143
+ * with. D-61: `catalog` declares `inventory` `degrades-without`, and the
144
+ * degrade is the empty map — availability is an indication on a catalog
145
+ * read, never a reason to fail one.
146
+ *
147
+ * The probe comes **before** the resolution and there is no `catch`. A
148
+ * closed gate throws rather than resolving to `undefined`, so optional
149
+ * chaining would defend against nothing, and a `catch` would swallow a
150
+ * genuine `inventory` failure along with the absence — which is what this
151
+ * closure did before D-61.
152
+ */
153
+ catalogExternalAvailability: ctx
154
+ .asFunction(() => {
155
+ const availability = lazyPort(ctx, 'inventoryAvailabilityPort');
156
+ return async (productIds, salesChannelId) => {
157
+ if (!effectiveState.isPresent('inventory')) {
158
+ return new Map();
159
+ }
160
+ return availability.resolveAvailabilityBands(productIds, salesChannelId);
161
+ };
162
+ })
163
+ .singleton(),
164
+ /**
165
+ * The full Meilisearch reindex an attribute's `searchable` flip runs, as a
166
+ * `search_reindex` bulk operation.
167
+ *
168
+ * Probed for the same reason the availability read is: with `search` off
169
+ * there is no index to rebuild, so "nothing was indexed" is the honest
170
+ * answer and 503-ing an attribute edit is not. The alternative — letting
171
+ * the gate throw — would make an operator's supported off-switch fail an
172
+ * unrelated admin write.
173
+ */
174
+ catalogSearchReindex: ctx
175
+ .asFunction(() => {
176
+ const reindex = lazyPort(ctx, 'searchReindexPort');
177
+ return async () => {
178
+ if (!effectiveState.isPresent('search'))
179
+ return { documentCount: 0 };
180
+ return reindex.reindexAll();
181
+ };
182
+ })
183
+ .singleton(),
184
+ /**
185
+ * The storefront product-image placeholder
186
+ * (`general.product_image_placeholder_url`), resolved per channel.
187
+ *
188
+ * An unknown code falls back to the system-default channel, which always
189
+ * exists (D-48); the placeholder is a per-storefront property, so the
190
+ * default channel's value is the wanted answer and not the platform-wide
191
+ * one. Both names are the **platform's** registrations, so this is not a
192
+ * module edge and needs no manifest entry.
193
+ *
194
+ * The `catch` stays and is not a port catch: a placeholder is decoration on
195
+ * a product listing, and a settings hiccup must not break one.
196
+ */
197
+ catalogImagePlaceholderUrl: ctx
198
+ .asFunction(() => {
199
+ const cradle = () => ctx.cradle();
200
+ return async (salesChannelCode) => {
201
+ try {
202
+ const channels = cradle().salesChannelResolutionPort;
203
+ const channelId = (salesChannelCode ? await channels.getByCode(salesChannelCode) : null)?.id ??
204
+ (await channels.getSystemDefault()).id;
205
+ const url = await cradle().settingsReadPort.get('product_image_placeholder_url', channelId, z.string());
206
+ const trimmed = url.trim();
207
+ return trimmed === '' ? null : trimmed;
208
+ }
209
+ catch {
210
+ return null;
211
+ }
212
+ };
213
+ })
214
+ .singleton(),
215
+ /**
216
+ * Feature 068 — the storefront serves the category tree from a fetch cache
217
+ * tagged `catalog:categories`, flushed on every category write so an
218
+ * activation toggle shows immediately. A no-op unless STOREFRONT_BASE_URL
219
+ * and REVALIDATE_SECRET are configured.
220
+ *
221
+ * Registered here rather than built in the plugin body because the
222
+ * subscription that drives it belongs in this file (issue #107); the plugin
223
+ * still hands it `app.log` when the Fastify instance exists.
224
+ */
225
+ catalogCategoryRevalidator: ctx
226
+ .asFunction(() => new StorefrontRevalidator({
227
+ baseUrl: process.env['STOREFRONT_BASE_URL'],
228
+ secret: process.env['REVALIDATE_SECRET'],
229
+ }))
230
+ .singleton(),
231
+ catalog: ctx
232
+ .asFunction(({ emFactory, eventBus, commandBus, auditLogService, moduleQueueRedis, catalogRunBulkOperationWorker, }) => catalogModule({
233
+ emFactory,
234
+ eventBus,
235
+ commandBus,
236
+ auditLogService,
237
+ ...(moduleQueueRedis === undefined ? {} : { redis: moduleQueueRedis }),
238
+ runBulkOperationWorker: catalogRunBulkOperationWorker,
239
+ // The lifecycle gate, threaded in rather than imported. The
240
+ // consumer is built inside the attach function — it needs `app.log`
241
+ // and an `onClose` hook — so `plugin.ts` has no `ModuleContext`
242
+ // where the worker exists; it called
243
+ // `defineModuleWorker('catalog', …)` for itself until T051, which
244
+ // `contracts/host-package.md` §1.4c classifies **A**. Same gate,
245
+ // through the seam a composed module is meant to use.
246
+ registerWorker: (worker, workerOptions) => {
247
+ ctx.worker(worker, workerOptions);
248
+ },
249
+ customFieldValues: lazyPort(ctx, 'customFieldValueService'),
250
+ // D-98.2 / issue #196 — the definition *read*, under the name a
251
+ // contract publishes. `customFieldDefinitionService` is the owner's
252
+ // own CRUD registration and answers a different question; it is
253
+ // still the apply seam below, which no contract can publish.
254
+ customFieldDefinitions: lazyPort(ctx, 'customFieldDefinitionReadPort'),
255
+ // The apply seam (D-77): every `apply*` method takes the caller's
256
+ // `EntityManager`, so it stays off `@endora-commerce/contracts` and keeps
257
+ // naming the owner's own registration.
258
+ customFieldsPort: lazyPort(ctx, 'customFieldDefinitionService'),
259
+ attributeReadService: lazyPort(ctx, 'catalogAttributeReadPort'),
260
+ pricingService: lazyPort(ctx, 'pricingService'),
261
+ salesChannelMembership: lazyPort(ctx, 'salesChannelMembershipPort'),
262
+ // Feature 075 — the *read* port rather than the whole admin service.
263
+ // The two consumers in this module ask two questions between them,
264
+ // `listActive` and `getDefault`, which is what `languageReadPort`
265
+ // publishes.
266
+ languageService: lazyPort(ctx, 'languageReadPort'),
267
+ // Absent from the harness before T142, so the bulk-operation
268
+ // completion notice and its e-mail ran in no test.
269
+ //
270
+ // D-60 — the bell's absence is decided here, in front of the gate,
271
+ // and reaches the bulk-operation service as `not-present` in the
272
+ // return type. A `catch` at the call site fused "the operator
273
+ // switched notifications off" with "the write failed".
274
+ adminNotificationService: presenceAwareBulkRecorder(
275
+ // D-98.2 / issue #196 — `adminNotificationRecordPort` is the name
276
+ // the contract publishes and the one that answers with a record;
277
+ // `adminNotificationService` is the class registration, whose
278
+ // `record` hands back the `AdminNotification` entity.
279
+ lazyPort(ctx, 'adminNotificationRecordPort')),
280
+ mailer: lazyPort(ctx, 'emailMailer'),
281
+ // Issue #153 — `search`'s listing backend, resolved rather than
282
+ // constructed. `plugin.ts` used to `new SearchQueryService(...)`
283
+ // out of `search`'s class, so a composition held two Meilisearch
284
+ // clients and the public product list reached the index through no
285
+ // gate at all. Whether the listing uses it is still decided before
286
+ // the call by `effectiveState.isPresent('search')`.
287
+ searchQueryService: lazyPort(ctx, 'searchQueryPort'),
288
+ // Feature 075 — `assets_library`'s read port. It fails closed, which
289
+ // is right for both of its uses: an attach that cannot verify the
290
+ // asset would store a dangling id, and a listing that cannot read
291
+ // the asset row has no image URL to render. The module declares
292
+ // `assets_library` in `dependencies`, so an operator cannot switch
293
+ // it off underneath this.
294
+ assets: lazyPort(ctx, 'assetReadPort'),
295
+ // Feature 075 — the external namespace's calling organisation, and
296
+ // the bulk-operation requester's e-mail address. Both were reads of
297
+ // another module's entity against another module's table.
298
+ organizations: lazyPort(ctx, 'organizationDetailsPort'),
299
+ adminUsers: lazyPort(ctx, 'adminUserReadPort'),
300
+ requireAdmin: (permission) => async (req, reply) => cradle().requireAdmin(permission)(req, reply),
301
+ requireApiKey: requireApiKeyGate,
302
+ requireBoundApiKey: requireBoundApiKeyGate,
303
+ resolveAdminAuditContext: (req) => cradle().catalogAdminAuditContext(req),
304
+ resolveExternalAvailability: (productIds, salesChannelId) => cradle().catalogExternalAvailability(productIds, salesChannelId),
305
+ resolveProductImagePlaceholderUrl: (salesChannelCode) => cradle().catalogImagePlaceholderUrl(salesChannelCode),
306
+ reindexSearchIndexes: () => cradle().catalogSearchReindex(),
307
+ categoryRevalidator: cradle().catalogCategoryRevalidator,
308
+ copyWarehouseThresholds,
309
+ }))
310
+ .singleton(),
311
+ });
312
+ // ---------------------------------------------------------------------------
313
+ // Feature 075, Phase P — the published surface.
314
+ //
315
+ // `catalog` is the heaviest provider in the tree: 107 inbound import sites
316
+ // across fourteen modules, sixty of them on the `Product` and `Category`
317
+ // entity classes. The nine ports below this block hand out *services*, which
318
+ // is what the sweep's consumers type themselves against; these five are what
319
+ // they rewire to, and none of them lets an entity across the boundary.
320
+ //
321
+ // The two read ports replace the sixty entity reads. The three adapters
322
+ // narrow three large admin services to the methods `pim_ergonode` and
323
+ // `promotions` measurably call — ten of `CatalogAdminService`'s hundred, two
324
+ // of `CatalogQueryService`'s.
325
+ //
326
+ // `product_feeds`' predicate-driven product scan was deliberately unmet here
327
+ // and escalated to the `product_feeds` cut, which ruled it: the module keeps
328
+ // its selection DSL and compiles it to `CatalogProductFilter` — a grammar
329
+ // narrower than MikroORM, published in `@endora-commerce/contracts` — and this module
330
+ // translates and runs it, with the eligibility floor and the keyset cursor
331
+ // inside `catalogProductFilterPort` rather than in the caller's conjunction.
332
+ // ---------------------------------------------------------------------------
333
+ ctx.di.providePort('catalogProductReadPort', ctx
334
+ .asFunction(({ emFactory }) => new CatalogProductReadService(emFactory))
335
+ .singleton());
336
+ ctx.di.providePort('catalogCategoryReadPort', ctx
337
+ .asFunction(({ emFactory }) => new CatalogCategoryReadService(emFactory))
338
+ .singleton());
339
+ /**
340
+ * The selection scan `product_feeds` walks a channel with. Separate from
341
+ * `catalogProductReadPort` because it answers a different question: that port
342
+ * resolves rows a caller can already name, this one *finds* them — and it is
343
+ * the only place the sellable floor and the keyset cursor are applied, so
344
+ * neither can be composed away by a caller.
345
+ */
346
+ ctx.di.providePort('catalogProductFilterPort', ctx
347
+ .asFunction(({ emFactory }) => new CatalogProductFilterService(emFactory))
348
+ .singleton());
349
+ ctx.di.providePort('catalogProductWritePort', ctx
350
+ .asFunction(() => createCatalogProductWritePort(() => ctx.cradle().catalogAdminService))
351
+ .singleton());
352
+ /**
353
+ * Feature 089 — channel/locale-scoped product value writes for PIM importers.
354
+ * Narrows `ProductOverridesService.applyBulk` so a foreign module never holds
355
+ * the class (and never reaches `product_value_overrides` by SQL).
356
+ */
357
+ ctx.di.providePort('catalogProductValueOverrideWritePort', ctx
358
+ .asFunction(({ emFactory, commandBus }) => {
359
+ const service = new ProductOverridesService(emFactory, lazyPort(ctx, 'salesChannelMembershipPort'), commandBus, lazyPort(ctx, 'catalogAttributeReadPort'));
360
+ return {
361
+ async applyBulk(productId, input) {
362
+ await service.applyBulk(productId, { upserts: [...input.upserts], deletes: [] });
363
+ },
364
+ };
365
+ })
366
+ .singleton());
367
+ /**
368
+ * The value-key rename seam (`specs/134-paid-module-extraction/research.md`
369
+ * D12). Its interface is on this module's `./ports` rather than in
370
+ * `@endora-commerce/contracts` because the method takes the caller's
371
+ * `EntityManager` (D-169, FR-034): the product values and `custom_fields`'
372
+ * definition key must move in one transaction.
373
+ */
374
+ ctx.di.providePort('catalogAttributeValueKeyPort', ctx.asFunction(() => new AttributeValueKeyService()).singleton());
375
+ ctx.di.providePort('catalogCategoryWritePort', ctx
376
+ .asFunction(() => createCatalogCategoryWritePort(() => ctx.cradle().categoryAdminService))
377
+ .singleton());
378
+ /**
379
+ * D-74 — the bulk import surface. `import_export` parses the spreadsheet;
380
+ * this module owns the validation, the within-run slug index, the transaction
381
+ * and the audit row, because every row a catalogue import writes lands in this
382
+ * module's tables and in nobody else's.
383
+ */
384
+ ctx.di.providePort('catalogBulkImportPort', ctx
385
+ .asFunction(({ commandBus }) => new CatalogBulkImportService(commandBus, lazyPort(ctx, 'salesChannelMembershipPort')))
386
+ .singleton());
387
+ /**
388
+ * Issue #174 — the buyer's type-ahead, which `quick_order` was answering
389
+ * with its own knex `select` against `products`.
390
+ *
391
+ * There was no import specifier, so `check:module-boundary` read clean over
392
+ * it and no ledger shard could key it; and the query filtered
393
+ * `status = 'active'` and nothing else, so a signed-in buyer saw every active
394
+ * product on the platform whatever channel they were shopping. The predicate
395
+ * is a catalogue question in every part — which rows are active, which are on
396
+ * the channel, and which attribute values are searchable — so it is published
397
+ * from here, scoped by `sales_channel_products` like every other
398
+ * customer-facing read in this module.
399
+ */
400
+ ctx.di.providePort('catalogQuickSearchPort', ctx
401
+ .asFunction(({ emFactory }) => new CatalogQuickSearchService(emFactory, lazyPort(ctx, 'catalogAttributeReadPort')))
402
+ .singleton());
403
+ ctx.di.providePort('catalogPromoAttributePort', ctx
404
+ .asFunction(() => createCatalogPromoAttributePort(() => ctx.cradle().catalogQueryPort))
405
+ .singleton());
406
+ // The nine ports. Seven of them were a second instance each root built for
407
+ // `pim_ergonode`; the last two are the `CatalogQueryService` and attribute
408
+ // read model that issue #44 recorded.
409
+ //
410
+ // Six of them gain a Phase-P contract type as their `providePort` parameter,
411
+ // which is the compile-time proof that the class still satisfies what was
412
+ // published. All six already returned contract DTOs, so none needed an
413
+ // adapter — the two that returned entities did, and are above.
414
+ ctx.di.providePort('catalogAttributeReadPort', ctx
415
+ .asFunction(({ emFactory }) => new CatalogAttributeReadService(emFactory,
416
+ // The definition read, under the published name (D-98.2).
417
+ lazyPort(ctx, 'customFieldDefinitionReadPort')))
418
+ .singleton());
419
+ ctx.di.providePort('catalogQueryPort', ctx
420
+ .asFunction(({ emFactory }) => new CatalogQueryService(emFactory, undefined, undefined, lazyPort(ctx, 'catalogAttributeReadPort'), lazyPort(ctx, 'pricingService'), lazyPort(ctx, 'assetReadPort'), lazyPort(ctx, 'salesChannelMembershipPort'), lazyPort(ctx, 'organizationDetailsPort'),
421
+ // Feature 086 — the ordering slice, off the same container and the
422
+ // same declared edge. Two `lazyPort` calls rather than one widened
423
+ // type, because a captured gate keeps answering after its owner is
424
+ // switched off and both of these are handed to a singleton.
425
+ lazyPort(ctx, 'pricingService'), ctx.log))
426
+ .singleton());
427
+ ctx.di.providePort('catalogAdminService', ctx
428
+ .asFunction(({ emFactory, eventBus, auditLogService, commandBus }) => new CatalogAdminService(emFactory, eventBus, auditLogService, lazyPort(ctx, 'salesChannelMembershipPort'), commandBus, lazyPort(ctx, 'catalogAttributeReadPort'),
429
+ // The apply seam, not the definition source. Both roots once passed
430
+ // the same service for this and for the definition source, which is
431
+ // why one name answered both questions; the read half names
432
+ // `customFieldDefinitionReadPort` now and this half stays here,
433
+ // unpublished by D-77 because every `apply*` method takes the
434
+ // caller's `EntityManager`.
435
+ //
436
+ // The type argument names the **owner's** interface rather than an
437
+ // indexed access into this module's own cradle: `lazyPort<T>` is an
438
+ // unchecked cast either way, and a cradle lookup reaches the owner's
439
+ // declaration by a route nothing states (!951's consumer-side
440
+ // finding, in the same shape).
441
+ lazyPort(ctx, 'customFieldDefinitionService'), copyWarehouseThresholds))
442
+ .singleton());
443
+ ctx.di.providePort('categoryAdminService', ctx
444
+ .asFunction(({ emFactory, commandBus }) => new CategoryAdminService(emFactory, lazyPort(ctx, 'salesChannelMembershipPort'), commandBus, lazyPort(ctx, 'customFieldValueService')))
445
+ .singleton());
446
+ ctx.di.providePort('attributeSetService', ctx
447
+ .asFunction(({ emFactory, commandBus }) => new AttributeSetService(emFactory, commandBus, lazyPort(ctx, 'catalogAttributeReadPort')))
448
+ .singleton());
449
+ ctx.di.providePort('galleryService', ctx
450
+ .asFunction(({ emFactory, commandBus }) => new GalleryService(emFactory, commandBus, lazyPort(ctx, 'assetReadPort')))
451
+ .singleton());
452
+ ctx.di.providePort('attachmentService', ctx
453
+ .asFunction(({ emFactory, commandBus }) => new AttachmentService(emFactory, commandBus, lazyPort(ctx, 'assetReadPort')))
454
+ .singleton());
455
+ ctx.di.providePort('productLinkService', ctx
456
+ .asFunction(({ emFactory, commandBus }) => new ProductLinkService(emFactory, commandBus, lazyPort(ctx, 'pricingService'), lazyPort(ctx, 'assetReadPort'), lazyPort(ctx, 'salesChannelMembershipPort'), lazyPort(ctx, 'organizationDetailsPort')))
457
+ .singleton());
458
+ ctx.di.providePort('groupedService', ctx
459
+ .asFunction(({ emFactory, commandBus }) => new GroupedService(emFactory, commandBus))
460
+ .singleton());
461
+ ctx.di.providePort('bundleService', ctx
462
+ .asFunction(({ emFactory, commandBus }) => new BundleService(emFactory, commandBus))
463
+ .singleton());
464
+ ctx.di.providePort('packagingUnitService', ctx
465
+ .asFunction(({ emFactory, commandBus }) => new PackagingUnitService(emFactory, commandBus))
466
+ .singleton());
467
+ /**
468
+ * FR-030 — the four edges that block deleting an asset this module points at
469
+ * (T143a): a gallery item, a product attachment, a virtual download and a
470
+ * category's main image.
471
+ *
472
+ * Both roots pushed these descriptors into `assets_library`' registry, so the
473
+ * "in use by" answer an operator got was assembled from whichever modules the
474
+ * *root* had been taught about — and `catalog` being switched off did not
475
+ * remove its four edges, because a root's registration passes through no
476
+ * lifecycle seam.
477
+ *
478
+ * `ctx.onBoot` rather than a registration: the registry is *read*, once per
479
+ * delete, by the module that owns it. Boot hooks run after every module has
480
+ * registered and before any request is served, so the edges are in place from
481
+ * the first delete on.
482
+ */
483
+ ctx.onBoot(() => {
484
+ const { assetReferenceRegistry, emFactory } = cradle();
485
+ registerCatalogAssetReferences(assetReferenceRegistry, emFactory);
486
+ });
487
+ /**
488
+ * The assistant tools this module contributes, and the bulk-progress reader
489
+ * that goes with them (D-44; D-72 point 4 for the second half).
490
+ *
491
+ * Both roots built these from `catalog`'s own services and pushed them into
492
+ * `prompt_actions`' registry, because pushing from here would have made
493
+ * `prompt_actions` a declared dependency — and that declaration is what would
494
+ * have made an optional assistant undeactivatable for as long as `catalog` is
495
+ * present. `nonBindingDependencies` is the declaration without that claim, so
496
+ * the contribution moves to the module whose services it is built from.
497
+ *
498
+ * The progress reader was the one of the five D-44 could not move, and not
499
+ * for a presence reason: `promptActionsBulkProgressResolver` was a single
500
+ * name `prompt_actions` defaulted, and a module may not write a name another
501
+ * module owns. Now that the host keeps a table instead, it pushes from here
502
+ * like everything else, and neither composition root names
503
+ * `catalog/prompt-tools.js`.
504
+ *
505
+ * A push, not a pull: nothing is read back out of either registry here. Both
506
+ * are plain `ctx.di.register`, so the resolution cannot ask a gate, and both
507
+ * drop an entry whose recorded owner is not effectively present — so a
508
+ * switched-off `catalog` contributes tools nobody can see and progress
509
+ * nobody folds in, and a switched-off `prompt_actions` holds two tables
510
+ * nobody walks.
511
+ */
512
+ ctx.onBoot(() => {
513
+ // `redis`, not `moduleQueueRedis`: this is the connection both roots handed
514
+ // these tools, and the harness deliberately registers the first while
515
+ // withholding the second. Switching to the queue-shaped name here would
516
+ // quietly stop the > 50-selection delegation in every test that exercises
517
+ // it, which is a behaviour change this move has no business making.
518
+ const deps = {
519
+ emFactory: cradle().emFactory,
520
+ events: cradle().eventBus,
521
+ auditLogService: cradle().auditLogService,
522
+ salesChannelMembership: cradle().salesChannelMembershipPort,
523
+ redis: cradle().redis,
524
+ };
525
+ const registry = cradle().promptActionToolRegistry;
526
+ for (const tool of [
527
+ ...catalogPromptResolverTools(deps),
528
+ ...catalogPromptMutationTools(deps),
529
+ ]) {
530
+ registry.register(tool);
531
+ }
532
+ cradle().promptActionBulkProgressRegistry.register('catalog', catalogBulkProgressReader(deps));
533
+ });
534
+ /**
535
+ * Feature 068's cache flush (issue #107).
536
+ *
537
+ * It was a bare `eventBus.on` in the plugin body, so a switched-off `catalog`
538
+ * still posted revalidation requests at the storefront on every category
539
+ * write. `ctx.subscribe` stops it with the module — and the storefront's own
540
+ * category surface is gone at that point anyway.
541
+ */
542
+ ctx.subscribe('category.updated.v1', () => {
543
+ void cradle().catalogCategoryRevalidator.revalidate(['catalog:categories']);
544
+ });
545
+ ctx.routes(async (app) => {
546
+ await cradle().catalog(app);
547
+ });
548
+ /**
549
+ * What an audit row about a product is called, and where the admin app shows it
550
+ * (feature 075, D-87 drain).
551
+ *
552
+ * `audit_logs` used to answer both by hand — one SQL statement naming this
553
+ * module's table, and this module's admin route spelled into its own switch.
554
+ * A read port would have been the wrong repair: `audit_logs` is a
555
+ * cross-cutting reader, and five ports into it would be five edges pointing
556
+ * from the record towards the things it records. One of the five contributors
557
+ * (`inventory`) is switchable, and `audit_logs` is `nonDeactivatable`, so that
558
+ * edge would also have taken the operator's switch away. A push costs nothing
559
+ * and reads the same for all five.
560
+ *
561
+ * A **contribution** hook: it pushes an inert resolver into
562
+ * `auditReferenceRegistry`, an ungated registry, and carries no presence probe
563
+ * (D-67/D-68). The registry's own enumeration policy is what drops this entry
564
+ * while the module is absent — probing here would make the drop survive a
565
+ * reactivation until the next restart.
566
+ */
567
+ ctx.onBoot(() => {
568
+ registerCatalogAuditReferences(lazyPort(ctx, 'auditReferenceRegistry'), cradle().emFactory);
569
+ });
570
+ }
571
+ /**
572
+ * Every entity class this module owns, as one array — the `./backend` subpath's
573
+ * contribution to the ORM (D-168).
574
+ *
575
+ * A module package publishes this array and **no entity class by name**, type-only
576
+ * exports included: `import { Product } from '@endora-commerce/mod-catalog/backend'`
577
+ * has to fail in a stranger's compiler, where none of this repository's checks run.
578
+ * A host program that has to construct one picks it out by name with `entityNamed`
579
+ * (`backend/src/packages/package-entity-lookup.ts`), which resolves against this
580
+ * array — the same one the ORM registered, so there is exactly one copy of each
581
+ * class in the process (D-160.6, D-160.6.1).
582
+ *
583
+ * The order is the one `db/entities-registry.generated.ts` declared before this
584
+ * module became a package, so the registered set is the same list in the same
585
+ * sequence.
586
+ */
587
+ export const entities = [
588
+ AttachmentType,
589
+ AttributeSetAttribute,
590
+ AttributeSet,
591
+ BulkOperation,
592
+ BundleSlotOption,
593
+ BundleSlot,
594
+ Category,
595
+ GalleryItemLabel,
596
+ GalleryItem,
597
+ GroupedItem,
598
+ ProductAttachment,
599
+ ProductAttribute,
600
+ ProductEditorPreference,
601
+ ProductLink,
602
+ ProductPackagingUnit,
603
+ ProductValueOverride,
604
+ ProductVariant,
605
+ Product,
606
+ ];
607
+ /**
608
+ * The catalogue read surface a host program needs, published **by name**.
609
+ *
610
+ * `src/seeds/demo-composition.ts` hands a `CatalogProductReadService` to
611
+ * `price_lists`' `DefaultPriceListMigrator`, and `src/seeds/attribute-fixtures.ts`
612
+ * maps a legacy attribute value type onto the unified custom-field model. Both are
613
+ * host programs in the **compiled** build (`node dist/cli.js demo seed`,
614
+ * documented in `deploy/README.md`), so neither may name this package's source: a
615
+ * filesystem path would evaluate the file a second time, and `backend/tsconfig.build.json`
616
+ * sets `rootDir: ./src`, which is TS6059 for a `.ts` outside it even under `import type`.
617
+ *
618
+ * D-168 bars an **entity class** from leaving by this door; a service and a pure
619
+ * mapping function are not entities, and `inventory`'s `WarehouseChannelReconciler` /
620
+ * `price_lists`' `DefaultPriceListMigrator` are the precedent for exactly this shape.
621
+ *
622
+ * `CatalogQueryService` is published as a **type** for `src/composition.ts`, which
623
+ * declares the cradle slot `promotions`, `quick_order` and `search` each resolve their
624
+ * own instance from. It is the same rewrite the root has already done for nine other
625
+ * packaged modules; a type import evaluates nothing, so it raises no second copy.
626
+ */
627
+ export { CatalogProductReadService } from './services/catalog-product-read.service.js';
628
+ export { legacyToCfType, } from './services/attribute-type-mapping.js';
629
+ /**
630
+ * The sales-channel membership bridges this module owns (feature 120, FR-015).
631
+ *
632
+ * Exported as well as registered because the owning module is the only honest
633
+ * source for it: a caller that composes no platform — the bare-database test
634
+ * harness, which constructs the kernel's membership service directly — declares
635
+ * these from here rather than from a list of nine it keeps itself, which is
636
+ * exactly the total map this feature deleted.
637
+ */
638
+ export const salesChannelBridges = [
639
+ { entityType: 'product', table: 'sales_channel_products', entityIdColumn: 'product_id' },
640
+ { entityType: 'category', table: 'sales_channel_categories', entityIdColumn: 'category_id' },
641
+ ];
642
+ //# sourceMappingURL=index.js.map