@open-mercato/core 0.9.1-develop.7474.1.51db10479d → 0.9.1-develop.7475.1.28ca93ed97

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 (597) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/catalog_price_history_entry/index.js +53 -0
  3. package/dist/generated/entities/catalog_price_history_entry/index.js.map +7 -0
  4. package/dist/generated/entities/customer_group_terms/index.js +2 -0
  5. package/dist/generated/entities/customer_group_terms/index.js.map +2 -2
  6. package/dist/generated/entities/ecommerce_store/index.js +33 -0
  7. package/dist/generated/entities/ecommerce_store/index.js.map +7 -0
  8. package/dist/generated/entities/ecommerce_store_channel_binding/index.js +29 -0
  9. package/dist/generated/entities/ecommerce_store_channel_binding/index.js.map +7 -0
  10. package/dist/generated/entities/ecommerce_store_domain_binding/index.js +23 -0
  11. package/dist/generated/entities/ecommerce_store_domain_binding/index.js.map +7 -0
  12. package/dist/generated/entities.ids.generated.js +8 -1
  13. package/dist/generated/entities.ids.generated.js.map +2 -2
  14. package/dist/generated/entity-fields-registry.js +72 -0
  15. package/dist/generated/entity-fields-registry.js.map +2 -2
  16. package/dist/helpers/integration/customerGroupsFixtures.js.map +2 -2
  17. package/dist/modules/catalog/acl.js +8 -1
  18. package/dist/modules/catalog/acl.js.map +2 -2
  19. package/dist/modules/catalog/api/config/omnibus/route.js +184 -0
  20. package/dist/modules/catalog/api/config/omnibus/route.js.map +7 -0
  21. package/dist/modules/catalog/api/prices/history/route.js +131 -0
  22. package/dist/modules/catalog/api/prices/history/route.js.map +7 -0
  23. package/dist/modules/catalog/api/prices/omnibus-preview/route.js +184 -0
  24. package/dist/modules/catalog/api/prices/omnibus-preview/route.js.map +7 -0
  25. package/dist/modules/catalog/api/products/route.js +54 -245
  26. package/dist/modules/catalog/api/products/route.js.map +3 -3
  27. package/dist/modules/catalog/api/tags/route.js +6 -0
  28. package/dist/modules/catalog/api/tags/route.js.map +2 -2
  29. package/dist/modules/catalog/backend/config/catalog/page.js +3 -1
  30. package/dist/modules/catalog/backend/config/catalog/page.js.map +2 -2
  31. package/dist/modules/catalog/cli.js +80 -2
  32. package/dist/modules/catalog/cli.js.map +2 -2
  33. package/dist/modules/catalog/commands/categories.js +51 -2
  34. package/dist/modules/catalog/commands/categories.js.map +2 -2
  35. package/dist/modules/catalog/commands/prices.js +43 -1
  36. package/dist/modules/catalog/commands/prices.js.map +2 -2
  37. package/dist/modules/catalog/commands/products.js +71 -0
  38. package/dist/modules/catalog/commands/products.js.map +2 -2
  39. package/dist/modules/catalog/commands/variants.js +7 -0
  40. package/dist/modules/catalog/commands/variants.js.map +2 -2
  41. package/dist/modules/catalog/components/OmnibusSettings.js +703 -0
  42. package/dist/modules/catalog/components/OmnibusSettings.js.map +7 -0
  43. package/dist/modules/catalog/components/PriceEditorOmnibusRow.js +152 -0
  44. package/dist/modules/catalog/components/PriceEditorOmnibusRow.js.map +7 -0
  45. package/dist/modules/catalog/components/lookupSources.js +31 -0
  46. package/dist/modules/catalog/components/lookupSources.js.map +7 -0
  47. package/dist/modules/catalog/components/prices/PriceScopeSelectors.js +8 -2
  48. package/dist/modules/catalog/components/prices/PriceScopeSelectors.js.map +2 -2
  49. package/dist/modules/catalog/components/products/VariantBuilder.js +11 -1
  50. package/dist/modules/catalog/components/products/VariantBuilder.js.map +2 -2
  51. package/dist/modules/catalog/data/entities.js +122 -1
  52. package/dist/modules/catalog/data/entities.js.map +2 -2
  53. package/dist/modules/catalog/data/validators.js +78 -0
  54. package/dist/modules/catalog/data/validators.js.map +2 -2
  55. package/dist/modules/catalog/di.js +18 -0
  56. package/dist/modules/catalog/di.js.map +2 -2
  57. package/dist/modules/catalog/lib/omnibus.js +285 -0
  58. package/dist/modules/catalog/lib/omnibus.js.map +7 -0
  59. package/dist/modules/catalog/lib/omnibusBackfill.js +146 -0
  60. package/dist/modules/catalog/lib/omnibusBackfill.js.map +7 -0
  61. package/dist/modules/catalog/lib/omnibusCache.js +89 -0
  62. package/dist/modules/catalog/lib/omnibusCache.js.map +7 -0
  63. package/dist/modules/catalog/lib/omnibusConfig.js +64 -0
  64. package/dist/modules/catalog/lib/omnibusConfig.js.map +7 -0
  65. package/dist/modules/catalog/lib/omnibusHistoryQueries.js +191 -0
  66. package/dist/modules/catalog/lib/omnibusHistoryQueries.js.map +7 -0
  67. package/dist/modules/catalog/lib/omnibusPresentedEntry.js +73 -0
  68. package/dist/modules/catalog/lib/omnibusPresentedEntry.js.map +7 -0
  69. package/dist/modules/catalog/lib/omnibusProductListEnrichment.js +94 -0
  70. package/dist/modules/catalog/lib/omnibusProductListEnrichment.js.map +7 -0
  71. package/dist/modules/catalog/lib/omnibusTypes.js +115 -0
  72. package/dist/modules/catalog/lib/omnibusTypes.js.map +7 -0
  73. package/dist/modules/catalog/lib/optionSchemaTranslations.js +55 -0
  74. package/dist/modules/catalog/lib/optionSchemaTranslations.js.map +7 -0
  75. package/dist/modules/catalog/lib/priceHistoryQuery.js +103 -0
  76. package/dist/modules/catalog/lib/priceHistoryQuery.js.map +7 -0
  77. package/dist/modules/catalog/lib/pricing.js +26 -2
  78. package/dist/modules/catalog/lib/pricing.js.map +2 -2
  79. package/dist/modules/catalog/lib/productFilters.js +273 -0
  80. package/dist/modules/catalog/lib/productFilters.js.map +7 -0
  81. package/dist/modules/catalog/lib/productScopeKeys.js +105 -0
  82. package/dist/modules/catalog/lib/productScopeKeys.js.map +7 -0
  83. package/dist/modules/catalog/lib/productScopeReindex.js +73 -0
  84. package/dist/modules/catalog/lib/productScopeReindex.js.map +7 -0
  85. package/dist/modules/catalog/migrations/Migration20261005105352_catalog.js +39 -0
  86. package/dist/modules/catalog/migrations/Migration20261005105352_catalog.js.map +7 -0
  87. package/dist/modules/catalog/migrations/Migration20261005150824_catalog.js +39 -0
  88. package/dist/modules/catalog/migrations/Migration20261005150824_catalog.js.map +7 -0
  89. package/dist/modules/catalog/services/catalogOmnibusService.js +480 -0
  90. package/dist/modules/catalog/services/catalogOmnibusService.js.map +7 -0
  91. package/dist/modules/catalog/setup.js +3 -1
  92. package/dist/modules/catalog/setup.js.map +2 -2
  93. package/dist/modules/catalog/subscribers/product-scope-keys-category-deleted.js +16 -0
  94. package/dist/modules/catalog/subscribers/product-scope-keys-category-deleted.js.map +7 -0
  95. package/dist/modules/catalog/subscribers/product-scope-keys-category-updated.js +17 -0
  96. package/dist/modules/catalog/subscribers/product-scope-keys-category-updated.js.map +7 -0
  97. package/dist/modules/catalog/translations.js +10 -0
  98. package/dist/modules/catalog/translations.js.map +2 -2
  99. package/dist/modules/configs/lib/upgrade-actions.js +28 -0
  100. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  101. package/dist/modules/customer_groups/api/customer-groups/[id]/terms/route.js +5 -0
  102. package/dist/modules/customer_groups/api/customer-groups/[id]/terms/route.js.map +2 -2
  103. package/dist/modules/customer_groups/components/CustomerGroupTermsSection.js +111 -3
  104. package/dist/modules/customer_groups/components/CustomerGroupTermsSection.js.map +2 -2
  105. package/dist/modules/customer_groups/components/customerGroupAssortmentScope.js +43 -0
  106. package/dist/modules/customer_groups/components/customerGroupAssortmentScope.js.map +7 -0
  107. package/dist/modules/customer_groups/data/entities.js +3 -0
  108. package/dist/modules/customer_groups/data/entities.js.map +2 -2
  109. package/dist/modules/customer_groups/data/validators.js +9 -0
  110. package/dist/modules/customer_groups/data/validators.js.map +2 -2
  111. package/dist/modules/customer_groups/migrations/Migration20261005110250_customer_groups.js +17 -0
  112. package/dist/modules/customer_groups/migrations/Migration20261005110250_customer_groups.js.map +7 -0
  113. package/dist/modules/customer_groups/services/customerGroupsService.js +62 -15
  114. package/dist/modules/customer_groups/services/customerGroupsService.js.map +2 -2
  115. package/dist/modules/ecommerce/acl.js +13 -0
  116. package/dist/modules/ecommerce/acl.js.map +7 -0
  117. package/dist/modules/ecommerce/api/domain-mappings/route.js +72 -0
  118. package/dist/modules/ecommerce/api/domain-mappings/route.js.map +7 -0
  119. package/dist/modules/ecommerce/api/openapi.js +27 -0
  120. package/dist/modules/ecommerce/api/openapi.js.map +7 -0
  121. package/dist/modules/ecommerce/api/store-channel-bindings/[id]/assortment-count/route.js +109 -0
  122. package/dist/modules/ecommerce/api/store-channel-bindings/[id]/assortment-count/route.js.map +7 -0
  123. package/dist/modules/ecommerce/api/store-channel-bindings/crud.js +265 -0
  124. package/dist/modules/ecommerce/api/store-channel-bindings/crud.js.map +7 -0
  125. package/dist/modules/ecommerce/api/store-channel-bindings/route.js +67 -0
  126. package/dist/modules/ecommerce/api/store-channel-bindings/route.js.map +7 -0
  127. package/dist/modules/ecommerce/api/store-domain-bindings/crud.js +296 -0
  128. package/dist/modules/ecommerce/api/store-domain-bindings/crud.js.map +7 -0
  129. package/dist/modules/ecommerce/api/store-domain-bindings/route.js +73 -0
  130. package/dist/modules/ecommerce/api/store-domain-bindings/route.js.map +7 -0
  131. package/dist/modules/ecommerce/api/storefront/categories/[slug]/route.js +87 -0
  132. package/dist/modules/ecommerce/api/storefront/categories/[slug]/route.js.map +7 -0
  133. package/dist/modules/ecommerce/api/storefront/categories/openapiSchemas.js +50 -0
  134. package/dist/modules/ecommerce/api/storefront/categories/openapiSchemas.js.map +7 -0
  135. package/dist/modules/ecommerce/api/storefront/categories/route.js +75 -0
  136. package/dist/modules/ecommerce/api/storefront/categories/route.js.map +7 -0
  137. package/dist/modules/ecommerce/api/storefront/context/route.js +163 -0
  138. package/dist/modules/ecommerce/api/storefront/context/route.js.map +7 -0
  139. package/dist/modules/ecommerce/api/storefront/products/[idOrHandle]/route.js +87 -0
  140. package/dist/modules/ecommerce/api/storefront/products/[idOrHandle]/route.js.map +7 -0
  141. package/dist/modules/ecommerce/api/storefront/products/openapiSchemas.js +177 -0
  142. package/dist/modules/ecommerce/api/storefront/products/openapiSchemas.js.map +7 -0
  143. package/dist/modules/ecommerce/api/storefront/products/route.js +78 -0
  144. package/dist/modules/ecommerce/api/storefront/products/route.js.map +7 -0
  145. package/dist/modules/ecommerce/api/storefront/search/suggest/openapiSchemas.js +25 -0
  146. package/dist/modules/ecommerce/api/storefront/search/suggest/openapiSchemas.js.map +7 -0
  147. package/dist/modules/ecommerce/api/storefront/search/suggest/route.js +75 -0
  148. package/dist/modules/ecommerce/api/storefront/search/suggest/route.js.map +7 -0
  149. package/dist/modules/ecommerce/api/storefront/storefrontRouteSupport.js +58 -0
  150. package/dist/modules/ecommerce/api/storefront/storefrontRouteSupport.js.map +7 -0
  151. package/dist/modules/ecommerce/api/stores/[id]/branding/route.js +183 -0
  152. package/dist/modules/ecommerce/api/stores/[id]/branding/route.js.map +7 -0
  153. package/dist/modules/ecommerce/api/stores/[id]/preview-branding/route.js +92 -0
  154. package/dist/modules/ecommerce/api/stores/[id]/preview-branding/route.js.map +7 -0
  155. package/dist/modules/ecommerce/api/stores/crud.js +401 -0
  156. package/dist/modules/ecommerce/api/stores/crud.js.map +7 -0
  157. package/dist/modules/ecommerce/api/stores/route.js +64 -0
  158. package/dist/modules/ecommerce/api/stores/route.js.map +7 -0
  159. package/dist/modules/ecommerce/backend/config/ecommerce/[id]/page.js +9 -0
  160. package/dist/modules/ecommerce/backend/config/ecommerce/[id]/page.js.map +7 -0
  161. package/dist/modules/ecommerce/backend/config/ecommerce/[id]/page.meta.js +16 -0
  162. package/dist/modules/ecommerce/backend/config/ecommerce/[id]/page.meta.js.map +7 -0
  163. package/dist/modules/ecommerce/backend/config/ecommerce/page.js +9 -0
  164. package/dist/modules/ecommerce/backend/config/ecommerce/page.js.map +7 -0
  165. package/dist/modules/ecommerce/backend/config/ecommerce/page.meta.js +16 -0
  166. package/dist/modules/ecommerce/backend/config/ecommerce/page.meta.js.map +7 -0
  167. package/dist/modules/ecommerce/commands/stores.js +110 -0
  168. package/dist/modules/ecommerce/commands/stores.js.map +7 -0
  169. package/dist/modules/ecommerce/components/ChannelAssortmentCount.js +90 -0
  170. package/dist/modules/ecommerce/components/ChannelAssortmentCount.js.map +7 -0
  171. package/dist/modules/ecommerce/components/ChannelBindingFormSections.js +33 -0
  172. package/dist/modules/ecommerce/components/ChannelBindingFormSections.js.map +7 -0
  173. package/dist/modules/ecommerce/components/ChannelLookupPicker.js +11 -0
  174. package/dist/modules/ecommerce/components/ChannelLookupPicker.js.map +7 -0
  175. package/dist/modules/ecommerce/components/DomainStatusWarning.js +24 -0
  176. package/dist/modules/ecommerce/components/DomainStatusWarning.js.map +7 -0
  177. package/dist/modules/ecommerce/components/StoreAvailabilityDefaultsSection.js +190 -0
  178. package/dist/modules/ecommerce/components/StoreAvailabilityDefaultsSection.js.map +7 -0
  179. package/dist/modules/ecommerce/components/StoreBrandingControls.js +67 -0
  180. package/dist/modules/ecommerce/components/StoreBrandingControls.js.map +7 -0
  181. package/dist/modules/ecommerce/components/StoreBrandingPreview.js +69 -0
  182. package/dist/modules/ecommerce/components/StoreBrandingPreview.js.map +7 -0
  183. package/dist/modules/ecommerce/components/StoreBrandingTab.js +218 -0
  184. package/dist/modules/ecommerce/components/StoreBrandingTab.js.map +7 -0
  185. package/dist/modules/ecommerce/components/StoreChannelBindingDialog.js +270 -0
  186. package/dist/modules/ecommerce/components/StoreChannelBindingDialog.js.map +7 -0
  187. package/dist/modules/ecommerce/components/StoreChannelsTab.js +313 -0
  188. package/dist/modules/ecommerce/components/StoreChannelsTab.js.map +7 -0
  189. package/dist/modules/ecommerce/components/StoreCreateDialog.js +164 -0
  190. package/dist/modules/ecommerce/components/StoreCreateDialog.js.map +7 -0
  191. package/dist/modules/ecommerce/components/StoreDomainBindingDialog.js +162 -0
  192. package/dist/modules/ecommerce/components/StoreDomainBindingDialog.js.map +7 -0
  193. package/dist/modules/ecommerce/components/StoreDomainsTab.js +357 -0
  194. package/dist/modules/ecommerce/components/StoreDomainsTab.js.map +7 -0
  195. package/dist/modules/ecommerce/components/StoreEditPage.js +155 -0
  196. package/dist/modules/ecommerce/components/StoreEditPage.js.map +7 -0
  197. package/dist/modules/ecommerce/components/StoreGeneralTab.js +167 -0
  198. package/dist/modules/ecommerce/components/StoreGeneralTab.js.map +7 -0
  199. package/dist/modules/ecommerce/components/StoreListPage.js +290 -0
  200. package/dist/modules/ecommerce/components/StoreListPage.js.map +7 -0
  201. package/dist/modules/ecommerce/components/StoreSeoTab.js +132 -0
  202. package/dist/modules/ecommerce/components/StoreSeoTab.js.map +7 -0
  203. package/dist/modules/ecommerce/components/StoreStatusBadge.js +20 -0
  204. package/dist/modules/ecommerce/components/StoreStatusBadge.js.map +7 -0
  205. package/dist/modules/ecommerce/components/channelLookups.js +28 -0
  206. package/dist/modules/ecommerce/components/channelLookups.js.map +7 -0
  207. package/dist/modules/ecommerce/components/storeAdmin.js +41 -0
  208. package/dist/modules/ecommerce/components/storeAdmin.js.map +7 -0
  209. package/dist/modules/ecommerce/components/storeBrandingForm.js +197 -0
  210. package/dist/modules/ecommerce/components/storeBrandingForm.js.map +7 -0
  211. package/dist/modules/ecommerce/components/storeChannels.js +140 -0
  212. package/dist/modules/ecommerce/components/storeChannels.js.map +7 -0
  213. package/dist/modules/ecommerce/components/storeDomains.js +167 -0
  214. package/dist/modules/ecommerce/components/storeDomains.js.map +7 -0
  215. package/dist/modules/ecommerce/components/storeEditTabs.js +62 -0
  216. package/dist/modules/ecommerce/components/storeEditTabs.js.map +7 -0
  217. package/dist/modules/ecommerce/components/storeGeneral.js +95 -0
  218. package/dist/modules/ecommerce/components/storeGeneral.js.map +7 -0
  219. package/dist/modules/ecommerce/components/storeSeo.js +69 -0
  220. package/dist/modules/ecommerce/components/storeSeo.js.map +7 -0
  221. package/dist/modules/ecommerce/components/useChannelAssortmentCount.js +45 -0
  222. package/dist/modules/ecommerce/components/useChannelAssortmentCount.js.map +7 -0
  223. package/dist/modules/ecommerce/components/useStoreAccess.js +28 -0
  224. package/dist/modules/ecommerce/components/useStoreAccess.js.map +7 -0
  225. package/dist/modules/ecommerce/data/enrichers.js +157 -0
  226. package/dist/modules/ecommerce/data/enrichers.js.map +7 -0
  227. package/dist/modules/ecommerce/data/entities.js +197 -0
  228. package/dist/modules/ecommerce/data/entities.js.map +7 -0
  229. package/dist/modules/ecommerce/data/validators.js +406 -0
  230. package/dist/modules/ecommerce/data/validators.js.map +7 -0
  231. package/dist/modules/ecommerce/di.js +11 -0
  232. package/dist/modules/ecommerce/di.js.map +7 -0
  233. package/dist/modules/ecommerce/events.js +27 -0
  234. package/dist/modules/ecommerce/events.js.map +7 -0
  235. package/dist/modules/ecommerce/index.js +16 -0
  236. package/dist/modules/ecommerce/index.js.map +7 -0
  237. package/dist/modules/ecommerce/lib/assortmentCount.js +112 -0
  238. package/dist/modules/ecommerce/lib/assortmentCount.js.map +7 -0
  239. package/dist/modules/ecommerce/lib/brandingStyles.js +184 -0
  240. package/dist/modules/ecommerce/lib/brandingStyles.js.map +7 -0
  241. package/dist/modules/ecommerce/lib/buyerContext.js +284 -0
  242. package/dist/modules/ecommerce/lib/buyerContext.js.map +7 -0
  243. package/dist/modules/ecommerce/lib/cacheInvalidation.js +186 -0
  244. package/dist/modules/ecommerce/lib/cacheInvalidation.js.map +7 -0
  245. package/dist/modules/ecommerce/lib/cacheKeys.js +236 -0
  246. package/dist/modules/ecommerce/lib/cacheKeys.js.map +7 -0
  247. package/dist/modules/ecommerce/lib/createConflictRecheck.js +29 -0
  248. package/dist/modules/ecommerce/lib/createConflictRecheck.js.map +7 -0
  249. package/dist/modules/ecommerce/lib/crudEvents.js +94 -0
  250. package/dist/modules/ecommerce/lib/crudEvents.js.map +7 -0
  251. package/dist/modules/ecommerce/lib/crudSupport.js +64 -0
  252. package/dist/modules/ecommerce/lib/crudSupport.js.map +7 -0
  253. package/dist/modules/ecommerce/lib/domainBindingRebind.js +99 -0
  254. package/dist/modules/ecommerce/lib/domainBindingRebind.js.map +7 -0
  255. package/dist/modules/ecommerce/lib/domainMappingSummaries.js +39 -0
  256. package/dist/modules/ecommerce/lib/domainMappingSummaries.js.map +7 -0
  257. package/dist/modules/ecommerce/lib/exclusiveFlag.js +57 -0
  258. package/dist/modules/ecommerce/lib/exclusiveFlag.js.map +7 -0
  259. package/dist/modules/ecommerce/lib/references.js +70 -0
  260. package/dist/modules/ecommerce/lib/references.js.map +7 -0
  261. package/dist/modules/ecommerce/lib/seedDraftStore.js +99 -0
  262. package/dist/modules/ecommerce/lib/seedDraftStore.js.map +7 -0
  263. package/dist/modules/ecommerce/lib/storeBindingCascade.js +109 -0
  264. package/dist/modules/ecommerce/lib/storeBindingCascade.js.map +7 -0
  265. package/dist/modules/ecommerce/lib/storeBranding.js +40 -0
  266. package/dist/modules/ecommerce/lib/storeBranding.js.map +7 -0
  267. package/dist/modules/ecommerce/lib/storeBrandingRoute.js +76 -0
  268. package/dist/modules/ecommerce/lib/storeBrandingRoute.js.map +7 -0
  269. package/dist/modules/ecommerce/lib/storeContext.js +393 -0
  270. package/dist/modules/ecommerce/lib/storeContext.js.map +7 -0
  271. package/dist/modules/ecommerce/lib/storeContextService.js +43 -0
  272. package/dist/modules/ecommerce/lib/storeContextService.js.map +7 -0
  273. package/dist/modules/ecommerce/lib/storeLocale.js +60 -0
  274. package/dist/modules/ecommerce/lib/storeLocale.js.map +7 -0
  275. package/dist/modules/ecommerce/lib/storeNotifications.js +41 -0
  276. package/dist/modules/ecommerce/lib/storeNotifications.js.map +7 -0
  277. package/dist/modules/ecommerce/lib/storefrontCatalogSupport.js +248 -0
  278. package/dist/modules/ecommerce/lib/storefrontCatalogSupport.js.map +7 -0
  279. package/dist/modules/ecommerce/lib/storefrontCategories.js +241 -0
  280. package/dist/modules/ecommerce/lib/storefrontCategories.js.map +7 -0
  281. package/dist/modules/ecommerce/lib/storefrontCategoryCache.js +71 -0
  282. package/dist/modules/ecommerce/lib/storefrontCategoryCache.js.map +7 -0
  283. package/dist/modules/ecommerce/lib/storefrontDetail.js +447 -0
  284. package/dist/modules/ecommerce/lib/storefrontDetail.js.map +7 -0
  285. package/dist/modules/ecommerce/lib/storefrontFacets.js +441 -0
  286. package/dist/modules/ecommerce/lib/storefrontFacets.js.map +7 -0
  287. package/dist/modules/ecommerce/lib/storefrontOptionFilter.js +15 -0
  288. package/dist/modules/ecommerce/lib/storefrontOptionFilter.js.map +7 -0
  289. package/dist/modules/ecommerce/lib/storefrontPricing.js +393 -0
  290. package/dist/modules/ecommerce/lib/storefrontPricing.js.map +7 -0
  291. package/dist/modules/ecommerce/lib/storefrontProductCache.js +90 -0
  292. package/dist/modules/ecommerce/lib/storefrontProductCache.js.map +7 -0
  293. package/dist/modules/ecommerce/lib/storefrontProductScope.js +107 -0
  294. package/dist/modules/ecommerce/lib/storefrontProductScope.js.map +7 -0
  295. package/dist/modules/ecommerce/lib/storefrontProducts.js +670 -0
  296. package/dist/modules/ecommerce/lib/storefrontProducts.js.map +7 -0
  297. package/dist/modules/ecommerce/lib/storefrontQuery.js +156 -0
  298. package/dist/modules/ecommerce/lib/storefrontQuery.js.map +7 -0
  299. package/dist/modules/ecommerce/lib/storefrontRateLimit.js +99 -0
  300. package/dist/modules/ecommerce/lib/storefrontRateLimit.js.map +7 -0
  301. package/dist/modules/ecommerce/lib/storefrontSearch.js +303 -0
  302. package/dist/modules/ecommerce/lib/storefrontSearch.js.map +7 -0
  303. package/dist/modules/ecommerce/lib/storefrontSearchCache.js +35 -0
  304. package/dist/modules/ecommerce/lib/storefrontSearchCache.js.map +7 -0
  305. package/dist/modules/ecommerce/lib/subscriberSupport.js +33 -0
  306. package/dist/modules/ecommerce/lib/subscriberSupport.js.map +7 -0
  307. package/dist/modules/ecommerce/lib/types.js +1 -0
  308. package/dist/modules/ecommerce/lib/types.js.map +7 -0
  309. package/dist/modules/ecommerce/migrations/Migration20261005113233_ecommerce.js +32 -0
  310. package/dist/modules/ecommerce/migrations/Migration20261005113233_ecommerce.js.map +7 -0
  311. package/dist/modules/ecommerce/migrations/Migration20261006112733_ecommerce.js +17 -0
  312. package/dist/modules/ecommerce/migrations/Migration20261006112733_ecommerce.js.map +7 -0
  313. package/dist/modules/ecommerce/notifications.client.js +47 -0
  314. package/dist/modules/ecommerce/notifications.client.js.map +7 -0
  315. package/dist/modules/ecommerce/notifications.js +48 -0
  316. package/dist/modules/ecommerce/notifications.js.map +7 -0
  317. package/dist/modules/ecommerce/search.js +83 -0
  318. package/dist/modules/ecommerce/search.js.map +7 -0
  319. package/dist/modules/ecommerce/setup.js +17 -0
  320. package/dist/modules/ecommerce/setup.js.map +7 -0
  321. package/dist/modules/ecommerce/subscribers/assortment-empty-notifications.js +14 -0
  322. package/dist/modules/ecommerce/subscribers/assortment-empty-notifications.js.map +7 -0
  323. package/dist/modules/ecommerce/subscribers/availability-policy-cache-invalidation.js +14 -0
  324. package/dist/modules/ecommerce/subscribers/availability-policy-cache-invalidation.js.map +7 -0
  325. package/dist/modules/ecommerce/subscribers/catalog-category-cache-invalidation.js +14 -0
  326. package/dist/modules/ecommerce/subscribers/catalog-category-cache-invalidation.js.map +7 -0
  327. package/dist/modules/ecommerce/subscribers/catalog-price-cache-invalidation.js +14 -0
  328. package/dist/modules/ecommerce/subscribers/catalog-price-cache-invalidation.js.map +7 -0
  329. package/dist/modules/ecommerce/subscribers/catalog-product-cache-invalidation.js +14 -0
  330. package/dist/modules/ecommerce/subscribers/catalog-product-cache-invalidation.js.map +7 -0
  331. package/dist/modules/ecommerce/subscribers/catalog-variant-cache-invalidation.js +14 -0
  332. package/dist/modules/ecommerce/subscribers/catalog-variant-cache-invalidation.js.map +7 -0
  333. package/dist/modules/ecommerce/subscribers/customer-group-cache-invalidation.js +14 -0
  334. package/dist/modules/ecommerce/subscribers/customer-group-cache-invalidation.js.map +7 -0
  335. package/dist/modules/ecommerce/subscribers/customer-group-membership-cache-invalidation.js +14 -0
  336. package/dist/modules/ecommerce/subscribers/customer-group-membership-cache-invalidation.js.map +7 -0
  337. package/dist/modules/ecommerce/subscribers/customer-group-terms-cache-invalidation.js +14 -0
  338. package/dist/modules/ecommerce/subscribers/customer-group-terms-cache-invalidation.js.map +7 -0
  339. package/dist/modules/ecommerce/subscribers/customer-user-deleted-cache-invalidation.js +14 -0
  340. package/dist/modules/ecommerce/subscribers/customer-user-deleted-cache-invalidation.js.map +7 -0
  341. package/dist/modules/ecommerce/subscribers/customer-user-updated-cache-invalidation.js +14 -0
  342. package/dist/modules/ecommerce/subscribers/customer-user-updated-cache-invalidation.js.map +7 -0
  343. package/dist/modules/ecommerce/subscribers/domain-binding-rebind.js +16 -0
  344. package/dist/modules/ecommerce/subscribers/domain-binding-rebind.js.map +7 -0
  345. package/dist/modules/ecommerce/subscribers/domain-mapping-cache-invalidation.js +14 -0
  346. package/dist/modules/ecommerce/subscribers/domain-mapping-cache-invalidation.js.map +7 -0
  347. package/dist/modules/ecommerce/subscribers/store-cache-invalidation.js +14 -0
  348. package/dist/modules/ecommerce/subscribers/store-cache-invalidation.js.map +7 -0
  349. package/dist/modules/ecommerce/subscribers/store-channel-binding-cache-invalidation.js +14 -0
  350. package/dist/modules/ecommerce/subscribers/store-channel-binding-cache-invalidation.js.map +7 -0
  351. package/dist/modules/ecommerce/subscribers/store-domain-binding-cache-invalidation.js +14 -0
  352. package/dist/modules/ecommerce/subscribers/store-domain-binding-cache-invalidation.js.map +7 -0
  353. package/dist/modules/ecommerce/subscribers/store-notifications.js +14 -0
  354. package/dist/modules/ecommerce/subscribers/store-notifications.js.map +7 -0
  355. package/dist/modules/query_index/lib/batch.js +23 -9
  356. package/dist/modules/query_index/lib/batch.js.map +2 -2
  357. package/dist/modules/query_index/lib/doc-enrichers.js +212 -0
  358. package/dist/modules/query_index/lib/doc-enrichers.js.map +7 -0
  359. package/dist/modules/query_index/lib/document.js +2 -0
  360. package/dist/modules/query_index/lib/document.js.map +2 -2
  361. package/dist/modules/query_index/lib/engine.js +68 -1
  362. package/dist/modules/query_index/lib/engine.js.map +2 -2
  363. package/dist/modules/query_index/lib/indexer.js +7 -0
  364. package/dist/modules/query_index/lib/indexer.js.map +2 -2
  365. package/dist/modules/query_index/lib/search-tokens.js +2 -0
  366. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  367. package/dist/modules/query_index/migrations/Migration20261005201500_query_index.js +17 -0
  368. package/dist/modules/query_index/migrations/Migration20261005201500_query_index.js.map +7 -0
  369. package/dist/modules/translations/components/TranslationManager.js +3 -3
  370. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  371. package/dist/modules/translations/data/validators.js +1 -1
  372. package/dist/modules/translations/data/validators.js.map +1 -1
  373. package/dist/modules/translations/lib/batch.js +21 -1
  374. package/dist/modules/translations/lib/batch.js.map +2 -2
  375. package/dist/modules/translations/lib/helpers.js +3 -0
  376. package/dist/modules/translations/lib/helpers.js.map +2 -2
  377. package/dist/modules/translations/lib/resolve-field-list.js +14 -2
  378. package/dist/modules/translations/lib/resolve-field-list.js.map +2 -2
  379. package/generated/entities/catalog_price_history_entry/index.ts +25 -0
  380. package/generated/entities/customer_group_terms/index.ts +1 -0
  381. package/generated/entities/ecommerce_store/index.ts +15 -0
  382. package/generated/entities/ecommerce_store_channel_binding/index.ts +13 -0
  383. package/generated/entities/ecommerce_store_domain_binding/index.ts +10 -0
  384. package/generated/entities.ids.generated.ts +8 -1
  385. package/generated/entity-fields-registry.ts +72 -0
  386. package/package.json +7 -7
  387. package/src/helpers/integration/customerGroupsFixtures.ts +2 -0
  388. package/src/modules/auth/i18n/de.json +8 -0
  389. package/src/modules/auth/i18n/en.json +8 -0
  390. package/src/modules/auth/i18n/es.json +8 -0
  391. package/src/modules/auth/i18n/ko.json +8 -0
  392. package/src/modules/auth/i18n/pl.json +8 -0
  393. package/src/modules/catalog/AGENTS.md +5 -2
  394. package/src/modules/catalog/acl.ts +7 -0
  395. package/src/modules/catalog/api/config/omnibus/route.ts +204 -0
  396. package/src/modules/catalog/api/prices/history/route.ts +139 -0
  397. package/src/modules/catalog/api/prices/omnibus-preview/route.ts +202 -0
  398. package/src/modules/catalog/api/products/route.ts +53 -308
  399. package/src/modules/catalog/api/tags/route.ts +6 -0
  400. package/src/modules/catalog/backend/config/catalog/page.tsx +2 -0
  401. package/src/modules/catalog/cli.ts +84 -1
  402. package/src/modules/catalog/commands/categories.ts +54 -2
  403. package/src/modules/catalog/commands/prices.ts +43 -1
  404. package/src/modules/catalog/commands/products.ts +84 -1
  405. package/src/modules/catalog/commands/variants.ts +7 -0
  406. package/src/modules/catalog/components/OmnibusSettings.tsx +832 -0
  407. package/src/modules/catalog/components/PriceEditorOmnibusRow.tsx +219 -0
  408. package/src/modules/catalog/components/lookupSources.ts +29 -0
  409. package/src/modules/catalog/components/prices/PriceScopeSelectors.tsx +9 -0
  410. package/src/modules/catalog/components/products/VariantBuilder.tsx +9 -0
  411. package/src/modules/catalog/data/entities.ts +123 -1
  412. package/src/modules/catalog/data/validators.ts +118 -0
  413. package/src/modules/catalog/di.ts +23 -0
  414. package/src/modules/catalog/i18n/de.json +77 -0
  415. package/src/modules/catalog/i18n/en.json +77 -0
  416. package/src/modules/catalog/i18n/es.json +77 -0
  417. package/src/modules/catalog/i18n/ko.json +77 -0
  418. package/src/modules/catalog/i18n/pl.json +77 -0
  419. package/src/modules/catalog/lib/omnibus.ts +406 -0
  420. package/src/modules/catalog/lib/omnibusBackfill.ts +198 -0
  421. package/src/modules/catalog/lib/omnibusCache.ts +111 -0
  422. package/src/modules/catalog/lib/omnibusConfig.ts +73 -0
  423. package/src/modules/catalog/lib/omnibusHistoryQueries.ts +248 -0
  424. package/src/modules/catalog/lib/omnibusPresentedEntry.ts +76 -0
  425. package/src/modules/catalog/lib/omnibusProductListEnrichment.ts +125 -0
  426. package/src/modules/catalog/lib/omnibusTypes.ts +202 -0
  427. package/src/modules/catalog/lib/optionSchemaTranslations.ts +55 -0
  428. package/src/modules/catalog/lib/priceHistoryQuery.ts +155 -0
  429. package/src/modules/catalog/lib/pricing.ts +42 -4
  430. package/src/modules/catalog/lib/productFilters.ts +349 -0
  431. package/src/modules/catalog/lib/productScopeKeys.ts +162 -0
  432. package/src/modules/catalog/lib/productScopeReindex.ts +139 -0
  433. package/src/modules/catalog/migrations/.snapshot-open-mercato.json +572 -0
  434. package/src/modules/catalog/migrations/Migration20261005105352_catalog.ts +39 -0
  435. package/src/modules/catalog/migrations/Migration20261005150824_catalog.ts +39 -0
  436. package/src/modules/catalog/services/catalogOmnibusService.ts +642 -0
  437. package/src/modules/catalog/setup.ts +2 -0
  438. package/src/modules/catalog/subscribers/product-scope-keys-category-deleted.ts +18 -0
  439. package/src/modules/catalog/subscribers/product-scope-keys-category-updated.ts +19 -0
  440. package/src/modules/catalog/translations.ts +12 -0
  441. package/src/modules/configs/i18n/de.json +5 -1
  442. package/src/modules/configs/i18n/en.json +5 -1
  443. package/src/modules/configs/i18n/es.json +5 -1
  444. package/src/modules/configs/i18n/ko.json +5 -1
  445. package/src/modules/configs/i18n/pl.json +5 -1
  446. package/src/modules/configs/lib/upgrade-actions.ts +35 -0
  447. package/src/modules/customer_groups/api/customer-groups/[id]/terms/route.ts +7 -0
  448. package/src/modules/customer_groups/components/CustomerGroupTermsSection.tsx +124 -2
  449. package/src/modules/customer_groups/components/customerGroupAssortmentScope.ts +46 -0
  450. package/src/modules/customer_groups/data/entities.ts +4 -0
  451. package/src/modules/customer_groups/data/validators.ts +14 -0
  452. package/src/modules/customer_groups/i18n/de.json +12 -0
  453. package/src/modules/customer_groups/i18n/en.json +12 -0
  454. package/src/modules/customer_groups/i18n/es.json +12 -0
  455. package/src/modules/customer_groups/i18n/ko.json +12 -0
  456. package/src/modules/customer_groups/i18n/pl.json +12 -0
  457. package/src/modules/customer_groups/migrations/.snapshot-open-mercato.json +17 -0
  458. package/src/modules/customer_groups/migrations/Migration20261005110250_customer_groups.ts +15 -0
  459. package/src/modules/customer_groups/services/customerGroupsService.ts +74 -23
  460. package/src/modules/ecommerce/acl.ts +9 -0
  461. package/src/modules/ecommerce/api/domain-mappings/route.ts +76 -0
  462. package/src/modules/ecommerce/api/openapi.ts +28 -0
  463. package/src/modules/ecommerce/api/store-channel-bindings/[id]/assortment-count/route.ts +141 -0
  464. package/src/modules/ecommerce/api/store-channel-bindings/crud.ts +283 -0
  465. package/src/modules/ecommerce/api/store-channel-bindings/route.ts +67 -0
  466. package/src/modules/ecommerce/api/store-domain-bindings/crud.ts +324 -0
  467. package/src/modules/ecommerce/api/store-domain-bindings/route.ts +73 -0
  468. package/src/modules/ecommerce/api/storefront/categories/[slug]/route.ts +94 -0
  469. package/src/modules/ecommerce/api/storefront/categories/openapiSchemas.ts +63 -0
  470. package/src/modules/ecommerce/api/storefront/categories/route.ts +78 -0
  471. package/src/modules/ecommerce/api/storefront/context/route.ts +203 -0
  472. package/src/modules/ecommerce/api/storefront/products/[idOrHandle]/route.ts +94 -0
  473. package/src/modules/ecommerce/api/storefront/products/openapiSchemas.ts +193 -0
  474. package/src/modules/ecommerce/api/storefront/products/route.ts +81 -0
  475. package/src/modules/ecommerce/api/storefront/search/suggest/openapiSchemas.ts +25 -0
  476. package/src/modules/ecommerce/api/storefront/search/suggest/route.ts +78 -0
  477. package/src/modules/ecommerce/api/storefront/storefrontRouteSupport.ts +68 -0
  478. package/src/modules/ecommerce/api/stores/[id]/branding/route.ts +205 -0
  479. package/src/modules/ecommerce/api/stores/[id]/preview-branding/route.ts +99 -0
  480. package/src/modules/ecommerce/api/stores/crud.ts +457 -0
  481. package/src/modules/ecommerce/api/stores/route.ts +66 -0
  482. package/src/modules/ecommerce/backend/config/ecommerce/[id]/page.meta.ts +12 -0
  483. package/src/modules/ecommerce/backend/config/ecommerce/[id]/page.tsx +5 -0
  484. package/src/modules/ecommerce/backend/config/ecommerce/page.meta.ts +12 -0
  485. package/src/modules/ecommerce/backend/config/ecommerce/page.tsx +5 -0
  486. package/src/modules/ecommerce/commands/stores.ts +154 -0
  487. package/src/modules/ecommerce/components/ChannelAssortmentCount.tsx +138 -0
  488. package/src/modules/ecommerce/components/ChannelBindingFormSections.tsx +40 -0
  489. package/src/modules/ecommerce/components/ChannelLookupPicker.tsx +5 -0
  490. package/src/modules/ecommerce/components/DomainStatusWarning.tsx +32 -0
  491. package/src/modules/ecommerce/components/StoreAvailabilityDefaultsSection.tsx +219 -0
  492. package/src/modules/ecommerce/components/StoreBrandingControls.tsx +73 -0
  493. package/src/modules/ecommerce/components/StoreBrandingPreview.tsx +77 -0
  494. package/src/modules/ecommerce/components/StoreBrandingTab.tsx +242 -0
  495. package/src/modules/ecommerce/components/StoreChannelBindingDialog.tsx +306 -0
  496. package/src/modules/ecommerce/components/StoreChannelsTab.tsx +375 -0
  497. package/src/modules/ecommerce/components/StoreCreateDialog.tsx +204 -0
  498. package/src/modules/ecommerce/components/StoreDomainBindingDialog.tsx +198 -0
  499. package/src/modules/ecommerce/components/StoreDomainsTab.tsx +426 -0
  500. package/src/modules/ecommerce/components/StoreEditPage.tsx +193 -0
  501. package/src/modules/ecommerce/components/StoreGeneralTab.tsx +189 -0
  502. package/src/modules/ecommerce/components/StoreListPage.tsx +326 -0
  503. package/src/modules/ecommerce/components/StoreSeoTab.tsx +152 -0
  504. package/src/modules/ecommerce/components/StoreStatusBadge.tsx +22 -0
  505. package/src/modules/ecommerce/components/channelLookups.ts +24 -0
  506. package/src/modules/ecommerce/components/storeAdmin.ts +56 -0
  507. package/src/modules/ecommerce/components/storeBrandingForm.ts +230 -0
  508. package/src/modules/ecommerce/components/storeChannels.ts +210 -0
  509. package/src/modules/ecommerce/components/storeDomains.ts +221 -0
  510. package/src/modules/ecommerce/components/storeEditTabs.tsx +76 -0
  511. package/src/modules/ecommerce/components/storeGeneral.ts +155 -0
  512. package/src/modules/ecommerce/components/storeSeo.ts +78 -0
  513. package/src/modules/ecommerce/components/useChannelAssortmentCount.ts +67 -0
  514. package/src/modules/ecommerce/components/useStoreAccess.ts +36 -0
  515. package/src/modules/ecommerce/data/enrichers.ts +213 -0
  516. package/src/modules/ecommerce/data/entities.ts +168 -0
  517. package/src/modules/ecommerce/data/validators.ts +587 -0
  518. package/src/modules/ecommerce/di.ts +9 -0
  519. package/src/modules/ecommerce/events.ts +27 -0
  520. package/src/modules/ecommerce/i18n/de.json +341 -0
  521. package/src/modules/ecommerce/i18n/en.json +341 -0
  522. package/src/modules/ecommerce/i18n/es.json +341 -0
  523. package/src/modules/ecommerce/i18n/ko.json +341 -0
  524. package/src/modules/ecommerce/i18n/pl.json +341 -0
  525. package/src/modules/ecommerce/index.ts +14 -0
  526. package/src/modules/ecommerce/lib/assortmentCount.ts +175 -0
  527. package/src/modules/ecommerce/lib/brandingStyles.ts +215 -0
  528. package/src/modules/ecommerce/lib/buyerContext.ts +401 -0
  529. package/src/modules/ecommerce/lib/cacheInvalidation.ts +302 -0
  530. package/src/modules/ecommerce/lib/cacheKeys.ts +340 -0
  531. package/src/modules/ecommerce/lib/createConflictRecheck.ts +31 -0
  532. package/src/modules/ecommerce/lib/crudEvents.ts +128 -0
  533. package/src/modules/ecommerce/lib/crudSupport.ts +85 -0
  534. package/src/modules/ecommerce/lib/domainBindingRebind.ts +138 -0
  535. package/src/modules/ecommerce/lib/domainMappingSummaries.ts +71 -0
  536. package/src/modules/ecommerce/lib/exclusiveFlag.ts +90 -0
  537. package/src/modules/ecommerce/lib/references.ts +93 -0
  538. package/src/modules/ecommerce/lib/seedDraftStore.ts +125 -0
  539. package/src/modules/ecommerce/lib/storeBindingCascade.ts +138 -0
  540. package/src/modules/ecommerce/lib/storeBranding.ts +48 -0
  541. package/src/modules/ecommerce/lib/storeBrandingRoute.ts +91 -0
  542. package/src/modules/ecommerce/lib/storeContext.ts +669 -0
  543. package/src/modules/ecommerce/lib/storeContextService.ts +71 -0
  544. package/src/modules/ecommerce/lib/storeLocale.ts +88 -0
  545. package/src/modules/ecommerce/lib/storeNotifications.ts +55 -0
  546. package/src/modules/ecommerce/lib/storefrontCatalogSupport.ts +427 -0
  547. package/src/modules/ecommerce/lib/storefrontCategories.ts +419 -0
  548. package/src/modules/ecommerce/lib/storefrontCategoryCache.ts +113 -0
  549. package/src/modules/ecommerce/lib/storefrontDetail.ts +654 -0
  550. package/src/modules/ecommerce/lib/storefrontFacets.ts +697 -0
  551. package/src/modules/ecommerce/lib/storefrontOptionFilter.ts +44 -0
  552. package/src/modules/ecommerce/lib/storefrontPricing.ts +583 -0
  553. package/src/modules/ecommerce/lib/storefrontProductCache.ts +126 -0
  554. package/src/modules/ecommerce/lib/storefrontProductScope.ts +181 -0
  555. package/src/modules/ecommerce/lib/storefrontProducts.ts +963 -0
  556. package/src/modules/ecommerce/lib/storefrontQuery.ts +215 -0
  557. package/src/modules/ecommerce/lib/storefrontRateLimit.ts +126 -0
  558. package/src/modules/ecommerce/lib/storefrontSearch.ts +454 -0
  559. package/src/modules/ecommerce/lib/storefrontSearchCache.ts +49 -0
  560. package/src/modules/ecommerce/lib/subscriberSupport.ts +41 -0
  561. package/src/modules/ecommerce/lib/types.ts +69 -0
  562. package/src/modules/ecommerce/migrations/.snapshot-open-mercato.json +829 -0
  563. package/src/modules/ecommerce/migrations/Migration20261005113233_ecommerce.ts +32 -0
  564. package/src/modules/ecommerce/migrations/Migration20261006112733_ecommerce.ts +15 -0
  565. package/src/modules/ecommerce/notifications.client.ts +46 -0
  566. package/src/modules/ecommerce/notifications.ts +46 -0
  567. package/src/modules/ecommerce/search.ts +93 -0
  568. package/src/modules/ecommerce/setup.ts +15 -0
  569. package/src/modules/ecommerce/subscribers/assortment-empty-notifications.ts +12 -0
  570. package/src/modules/ecommerce/subscribers/availability-policy-cache-invalidation.ts +12 -0
  571. package/src/modules/ecommerce/subscribers/catalog-category-cache-invalidation.ts +12 -0
  572. package/src/modules/ecommerce/subscribers/catalog-price-cache-invalidation.ts +12 -0
  573. package/src/modules/ecommerce/subscribers/catalog-product-cache-invalidation.ts +12 -0
  574. package/src/modules/ecommerce/subscribers/catalog-variant-cache-invalidation.ts +12 -0
  575. package/src/modules/ecommerce/subscribers/customer-group-cache-invalidation.ts +12 -0
  576. package/src/modules/ecommerce/subscribers/customer-group-membership-cache-invalidation.ts +12 -0
  577. package/src/modules/ecommerce/subscribers/customer-group-terms-cache-invalidation.ts +12 -0
  578. package/src/modules/ecommerce/subscribers/customer-user-deleted-cache-invalidation.ts +12 -0
  579. package/src/modules/ecommerce/subscribers/customer-user-updated-cache-invalidation.ts +12 -0
  580. package/src/modules/ecommerce/subscribers/domain-binding-rebind.ts +14 -0
  581. package/src/modules/ecommerce/subscribers/domain-mapping-cache-invalidation.ts +12 -0
  582. package/src/modules/ecommerce/subscribers/store-cache-invalidation.ts +12 -0
  583. package/src/modules/ecommerce/subscribers/store-channel-binding-cache-invalidation.ts +12 -0
  584. package/src/modules/ecommerce/subscribers/store-domain-binding-cache-invalidation.ts +12 -0
  585. package/src/modules/ecommerce/subscribers/store-notifications.ts +12 -0
  586. package/src/modules/query_index/lib/batch.ts +25 -9
  587. package/src/modules/query_index/lib/doc-enrichers.ts +306 -0
  588. package/src/modules/query_index/lib/document.ts +2 -0
  589. package/src/modules/query_index/lib/engine.ts +58 -1
  590. package/src/modules/query_index/lib/indexer.ts +8 -0
  591. package/src/modules/query_index/lib/search-tokens.ts +2 -0
  592. package/src/modules/query_index/migrations/Migration20261005201500_query_index.ts +42 -0
  593. package/src/modules/translations/components/TranslationManager.tsx +3 -3
  594. package/src/modules/translations/data/validators.ts +1 -1
  595. package/src/modules/translations/lib/batch.ts +47 -0
  596. package/src/modules/translations/lib/helpers.ts +4 -0
  597. package/src/modules/translations/lib/resolve-field-list.ts +16 -2
@@ -227,6 +227,33 @@ export const entityFieldsRegistry: Record<string, Record<string, string>> = {
227
227
  "updated_at": "updated_at",
228
228
  "deleted_at": "deleted_at"
229
229
  },
230
+ "catalog_price_history_entry": {
231
+ "id": "id",
232
+ "tenant_id": "tenant_id",
233
+ "organization_id": "organization_id",
234
+ "price_id": "price_id",
235
+ "product_id": "product_id",
236
+ "variant_id": "variant_id",
237
+ "offer_id": "offer_id",
238
+ "channel_id": "channel_id",
239
+ "price_kind_id": "price_kind_id",
240
+ "price_kind_code": "price_kind_code",
241
+ "currency_code": "currency_code",
242
+ "unit_price_net": "unit_price_net",
243
+ "unit_price_gross": "unit_price_gross",
244
+ "tax_rate": "tax_rate",
245
+ "tax_amount": "tax_amount",
246
+ "min_quantity": "min_quantity",
247
+ "max_quantity": "max_quantity",
248
+ "starts_at": "starts_at",
249
+ "ends_at": "ends_at",
250
+ "recorded_at": "recorded_at",
251
+ "change_type": "change_type",
252
+ "source": "source",
253
+ "is_announced": "is_announced",
254
+ "idempotency_key": "idempotency_key",
255
+ "metadata": "metadata"
256
+ },
230
257
  "catalog_price_kind": {
231
258
  "id": "id",
232
259
  "organization_id": "organization_id",
@@ -868,6 +895,7 @@ export const entityFieldsRegistry: Record<string, Record<string, string>> = {
868
895
  "credit_currency_code": "credit_currency_code",
869
896
  "approval_required_above": "approval_required_above",
870
897
  "min_order_value": "min_order_value",
898
+ "assortment_scope": "assortment_scope",
871
899
  "metadata": "metadata",
872
900
  "created_at": "created_at",
873
901
  "updated_at": "updated_at",
@@ -1210,6 +1238,50 @@ export const entityFieldsRegistry: Record<string, Record<string, string>> = {
1210
1238
  "created_at": "created_at",
1211
1239
  "updated_at": "updated_at"
1212
1240
  },
1241
+ "ecommerce_store": {
1242
+ "id": "id",
1243
+ "organization_id": "organization_id",
1244
+ "tenant_id": "tenant_id",
1245
+ "code": "code",
1246
+ "name": "name",
1247
+ "slug": "slug",
1248
+ "status": "status",
1249
+ "default_locale": "default_locale",
1250
+ "supported_locales": "supported_locales",
1251
+ "default_currency_code": "default_currency_code",
1252
+ "is_primary": "is_primary",
1253
+ "settings": "settings",
1254
+ "created_at": "created_at",
1255
+ "updated_at": "updated_at",
1256
+ "deleted_at": "deleted_at"
1257
+ },
1258
+ "ecommerce_store_channel_binding": {
1259
+ "id": "id",
1260
+ "organization_id": "organization_id",
1261
+ "tenant_id": "tenant_id",
1262
+ "store_id": "store_id",
1263
+ "sales_channel_id": "sales_channel_id",
1264
+ "price_kind_id": "price_kind_id",
1265
+ "assortment_scope": "assortment_scope",
1266
+ "price_sort_fallback": "price_sort_fallback",
1267
+ "is_default": "is_default",
1268
+ "require_authentication": "require_authentication",
1269
+ "created_at": "created_at",
1270
+ "updated_at": "updated_at",
1271
+ "deleted_at": "deleted_at"
1272
+ },
1273
+ "ecommerce_store_domain_binding": {
1274
+ "id": "id",
1275
+ "organization_id": "organization_id",
1276
+ "tenant_id": "tenant_id",
1277
+ "store_id": "store_id",
1278
+ "domain_mapping_id": "domain_mapping_id",
1279
+ "path_prefix": "path_prefix",
1280
+ "is_primary": "is_primary",
1281
+ "created_at": "created_at",
1282
+ "updated_at": "updated_at",
1283
+ "deleted_at": "deleted_at"
1284
+ },
1213
1285
  "encryption_map": {
1214
1286
  "id": "id",
1215
1287
  "entity_id": "entity_id",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.9.1-develop.7474.1.51db10479d",
3
+ "version": "0.9.1-develop.7475.1.28ca93ed97",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -264,16 +264,16 @@
264
264
  "zod": "^4.4.3"
265
265
  },
266
266
  "peerDependencies": {
267
- "@open-mercato/ai-assistant": "0.9.1-develop.7474.1.51db10479d",
268
- "@open-mercato/shared": "0.9.1-develop.7474.1.51db10479d",
269
- "@open-mercato/ui": "0.9.1-develop.7474.1.51db10479d",
267
+ "@open-mercato/ai-assistant": "0.9.1-develop.7475.1.28ca93ed97",
268
+ "@open-mercato/shared": "0.9.1-develop.7475.1.28ca93ed97",
269
+ "@open-mercato/ui": "0.9.1-develop.7475.1.28ca93ed97",
270
270
  "react": "^19.0.0",
271
271
  "react-dom": "^19.0.0"
272
272
  },
273
273
  "devDependencies": {
274
- "@open-mercato/ai-assistant": "0.9.1-develop.7474.1.51db10479d",
275
- "@open-mercato/shared": "0.9.1-develop.7474.1.51db10479d",
276
- "@open-mercato/ui": "0.9.1-develop.7474.1.51db10479d",
274
+ "@open-mercato/ai-assistant": "0.9.1-develop.7475.1.28ca93ed97",
275
+ "@open-mercato/shared": "0.9.1-develop.7475.1.28ca93ed97",
276
+ "@open-mercato/ui": "0.9.1-develop.7475.1.28ca93ed97",
277
277
  "@testing-library/dom": "^10.4.1",
278
278
  "@testing-library/jest-dom": "^7.0.1",
279
279
  "@testing-library/react": "^16.3.3",
@@ -1,5 +1,6 @@
1
1
  import { randomInt } from 'node:crypto';
2
2
  import { expect, type APIRequestContext } from '@playwright/test';
3
+ import type { AssortmentScope } from '@open-mercato/shared/lib/catalog-visibility';
3
4
  import { apiRequest } from './api';
4
5
  import { expectId, readJsonSafe } from './generalFixtures';
5
6
 
@@ -114,6 +115,7 @@ export type CustomerGroupTermsFixtureInput = {
114
115
  creditCurrencyCode?: string | null;
115
116
  approvalRequiredAbove?: number | null;
116
117
  minOrderValue?: number | null;
118
+ assortmentScope?: AssortmentScope | null;
117
119
  metadata?: Record<string, unknown> | null;
118
120
  };
119
121
 
@@ -72,10 +72,12 @@
72
72
  "auth.acl.features.business_rules.view_logs": "View rule execution logs",
73
73
  "auth.acl.features.catalog.categories.manage": "Manage catalog categories",
74
74
  "auth.acl.features.catalog.categories.view": "View catalog categories",
75
+ "auth.acl.features.catalog.price_history.view": "Preisverlauf im Katalog anzeigen",
75
76
  "auth.acl.features.catalog.pricing.manage": "Manage catalog pricing",
76
77
  "auth.acl.features.catalog.products.manage": "Manage catalog products",
77
78
  "auth.acl.features.catalog.products.view": "View catalog products",
78
79
  "auth.acl.features.catalog.settings.manage": "Manage catalog settings",
80
+ "auth.acl.features.catalog.settings.view": "Katalogeinstellungen anzeigen",
79
81
  "auth.acl.features.catalog.variants.manage": "Manage catalog variants",
80
82
  "auth.acl.features.channel_apns.configure": "Configure APNs credentials",
81
83
  "auth.acl.features.channel_apns.view": "View APNs channel configuration",
@@ -176,6 +178,11 @@
176
178
  "auth.acl.features.documents.share": "Share documents",
177
179
  "auth.acl.features.documents.templates.manage": "Manage document templates",
178
180
  "auth.acl.features.documents.view": "View documents",
181
+ "auth.acl.features.ecommerce.branding.manage": "Shop-Branding verwalten",
182
+ "auth.acl.features.ecommerce.channels.manage": "Kanal-Bindungen des Shops verwalten",
183
+ "auth.acl.features.ecommerce.domains.manage": "Domain-Bindungen des Shops verwalten",
184
+ "auth.acl.features.ecommerce.stores.manage": "Shops verwalten",
185
+ "auth.acl.features.ecommerce.stores.view": "Shops anzeigen",
179
186
  "auth.acl.features.entities.definitions.manage": "Manage custom field definitions",
180
187
  "auth.acl.features.entities.definitions.view": "View custom field definitions",
181
188
  "auth.acl.features.entities.records.manage": "Manage records",
@@ -424,6 +431,7 @@
424
431
  "auth.acl.modules.dictionaries": "Shared Dictionaries",
425
432
  "auth.acl.modules.directory": "Directory (Tenants & Organizations)",
426
433
  "auth.acl.modules.documents": "Documents",
434
+ "auth.acl.modules.ecommerce": "E-Commerce-Shops",
427
435
  "auth.acl.modules.entities": "Custom Entities & Fields",
428
436
  "auth.acl.modules.eudr": "EUDR Compliance",
429
437
  "auth.acl.modules.example": "Example Module",
@@ -72,10 +72,12 @@
72
72
  "auth.acl.features.business_rules.view_logs": "View rule execution logs",
73
73
  "auth.acl.features.catalog.categories.manage": "Manage catalog categories",
74
74
  "auth.acl.features.catalog.categories.view": "View catalog categories",
75
+ "auth.acl.features.catalog.price_history.view": "View catalog price history",
75
76
  "auth.acl.features.catalog.pricing.manage": "Manage catalog pricing",
76
77
  "auth.acl.features.catalog.products.manage": "Manage catalog products",
77
78
  "auth.acl.features.catalog.products.view": "View catalog products",
78
79
  "auth.acl.features.catalog.settings.manage": "Manage catalog settings",
80
+ "auth.acl.features.catalog.settings.view": "View catalog settings",
79
81
  "auth.acl.features.catalog.variants.manage": "Manage catalog variants",
80
82
  "auth.acl.features.channel_apns.configure": "Configure APNs credentials",
81
83
  "auth.acl.features.channel_apns.view": "View APNs channel configuration",
@@ -176,6 +178,11 @@
176
178
  "auth.acl.features.documents.share": "Share documents",
177
179
  "auth.acl.features.documents.templates.manage": "Manage document templates",
178
180
  "auth.acl.features.documents.view": "View documents",
181
+ "auth.acl.features.ecommerce.branding.manage": "Manage store branding",
182
+ "auth.acl.features.ecommerce.channels.manage": "Manage store channel bindings",
183
+ "auth.acl.features.ecommerce.domains.manage": "Manage store domain bindings",
184
+ "auth.acl.features.ecommerce.stores.manage": "Manage stores",
185
+ "auth.acl.features.ecommerce.stores.view": "View stores",
179
186
  "auth.acl.features.entities.definitions.manage": "Manage custom field definitions",
180
187
  "auth.acl.features.entities.definitions.view": "View custom field definitions",
181
188
  "auth.acl.features.entities.records.manage": "Manage records",
@@ -424,6 +431,7 @@
424
431
  "auth.acl.modules.dictionaries": "Shared Dictionaries",
425
432
  "auth.acl.modules.directory": "Directory (Tenants & Organizations)",
426
433
  "auth.acl.modules.documents": "Documents",
434
+ "auth.acl.modules.ecommerce": "Ecommerce Stores",
427
435
  "auth.acl.modules.entities": "Custom Entities & Fields",
428
436
  "auth.acl.modules.eudr": "EUDR Compliance",
429
437
  "auth.acl.modules.example": "Example Module",
@@ -72,10 +72,12 @@
72
72
  "auth.acl.features.business_rules.view_logs": "View rule execution logs",
73
73
  "auth.acl.features.catalog.categories.manage": "Manage catalog categories",
74
74
  "auth.acl.features.catalog.categories.view": "View catalog categories",
75
+ "auth.acl.features.catalog.price_history.view": "Ver historial de precios del catálogo",
75
76
  "auth.acl.features.catalog.pricing.manage": "Manage catalog pricing",
76
77
  "auth.acl.features.catalog.products.manage": "Manage catalog products",
77
78
  "auth.acl.features.catalog.products.view": "View catalog products",
78
79
  "auth.acl.features.catalog.settings.manage": "Manage catalog settings",
80
+ "auth.acl.features.catalog.settings.view": "Ver configuración del catálogo",
79
81
  "auth.acl.features.catalog.variants.manage": "Manage catalog variants",
80
82
  "auth.acl.features.channel_apns.configure": "Configure APNs credentials",
81
83
  "auth.acl.features.channel_apns.view": "View APNs channel configuration",
@@ -176,6 +178,11 @@
176
178
  "auth.acl.features.documents.share": "Share documents",
177
179
  "auth.acl.features.documents.templates.manage": "Manage document templates",
178
180
  "auth.acl.features.documents.view": "View documents",
181
+ "auth.acl.features.ecommerce.branding.manage": "Gestionar la imagen de marca de la tienda",
182
+ "auth.acl.features.ecommerce.channels.manage": "Gestionar vinculaciones de canal de la tienda",
183
+ "auth.acl.features.ecommerce.domains.manage": "Gestionar vinculaciones de dominio de la tienda",
184
+ "auth.acl.features.ecommerce.stores.manage": "Gestionar tiendas",
185
+ "auth.acl.features.ecommerce.stores.view": "Ver tiendas",
179
186
  "auth.acl.features.entities.definitions.manage": "Manage custom field definitions",
180
187
  "auth.acl.features.entities.definitions.view": "View custom field definitions",
181
188
  "auth.acl.features.entities.records.manage": "Manage records",
@@ -424,6 +431,7 @@
424
431
  "auth.acl.modules.dictionaries": "Shared Dictionaries",
425
432
  "auth.acl.modules.directory": "Directory (Tenants & Organizations)",
426
433
  "auth.acl.modules.documents": "Documents",
434
+ "auth.acl.modules.ecommerce": "Tiendas de comercio electrónico",
427
435
  "auth.acl.modules.entities": "Custom Entities & Fields",
428
436
  "auth.acl.modules.eudr": "EUDR Compliance",
429
437
  "auth.acl.modules.example": "Example Module",
@@ -72,10 +72,12 @@
72
72
  "auth.acl.features.business_rules.view_logs": "View rule execution logs",
73
73
  "auth.acl.features.catalog.categories.manage": "Manage catalog categories",
74
74
  "auth.acl.features.catalog.categories.view": "View catalog categories",
75
+ "auth.acl.features.catalog.price_history.view": "카탈로그 가격 이력 보기",
75
76
  "auth.acl.features.catalog.pricing.manage": "Manage catalog pricing",
76
77
  "auth.acl.features.catalog.products.manage": "Manage catalog products",
77
78
  "auth.acl.features.catalog.products.view": "View catalog products",
78
79
  "auth.acl.features.catalog.settings.manage": "Manage catalog settings",
80
+ "auth.acl.features.catalog.settings.view": "카탈로그 설정 보기",
79
81
  "auth.acl.features.catalog.variants.manage": "Manage catalog variants",
80
82
  "auth.acl.features.channel_apns.configure": "Configure APNs credentials",
81
83
  "auth.acl.features.channel_apns.view": "View APNs channel configuration",
@@ -176,6 +178,11 @@
176
178
  "auth.acl.features.documents.share": "Share documents",
177
179
  "auth.acl.features.documents.templates.manage": "Manage document templates",
178
180
  "auth.acl.features.documents.view": "View documents",
181
+ "auth.acl.features.ecommerce.branding.manage": "스토어 브랜딩 관리",
182
+ "auth.acl.features.ecommerce.channels.manage": "스토어 채널 바인딩 관리",
183
+ "auth.acl.features.ecommerce.domains.manage": "스토어 도메인 바인딩 관리",
184
+ "auth.acl.features.ecommerce.stores.manage": "스토어 관리",
185
+ "auth.acl.features.ecommerce.stores.view": "스토어 보기",
179
186
  "auth.acl.features.entities.definitions.manage": "Manage custom field definitions",
180
187
  "auth.acl.features.entities.definitions.view": "View custom field definitions",
181
188
  "auth.acl.features.entities.records.manage": "Manage records",
@@ -424,6 +431,7 @@
424
431
  "auth.acl.modules.dictionaries": "Shared Dictionaries",
425
432
  "auth.acl.modules.directory": "Directory (Tenants & Organizations)",
426
433
  "auth.acl.modules.documents": "Documents",
434
+ "auth.acl.modules.ecommerce": "이커머스 스토어",
427
435
  "auth.acl.modules.entities": "Custom Entities & Fields",
428
436
  "auth.acl.modules.eudr": "EUDR Compliance",
429
437
  "auth.acl.modules.example": "Example Module",
@@ -72,10 +72,12 @@
72
72
  "auth.acl.features.business_rules.view_logs": "Wyświetl dzienniki wykonywania reguł",
73
73
  "auth.acl.features.catalog.categories.manage": "Zarządzaj kategoriami katalogu",
74
74
  "auth.acl.features.catalog.categories.view": "Wyświetl kategorie katalogu",
75
+ "auth.acl.features.catalog.price_history.view": "Wyświetlaj historię cen w katalogu",
75
76
  "auth.acl.features.catalog.pricing.manage": "Zarządzaj cenami w katalogu",
76
77
  "auth.acl.features.catalog.products.manage": "Zarządzaj produktami w katalogu",
77
78
  "auth.acl.features.catalog.products.view": "Wyświetl produkty w katalogu",
78
79
  "auth.acl.features.catalog.settings.manage": "Zarządzaj ustawieniami katalogu",
80
+ "auth.acl.features.catalog.settings.view": "Wyświetlaj ustawienia katalogu",
79
81
  "auth.acl.features.catalog.variants.manage": "Zarządzaj wariantami w katalogu",
80
82
  "auth.acl.features.channel_apns.configure": "Konfiguruj dane dostępowe APNs",
81
83
  "auth.acl.features.channel_apns.view": "Wyświetl konfigurację kanału APNs",
@@ -176,6 +178,11 @@
176
178
  "auth.acl.features.documents.share": "Udostępniaj dokumenty",
177
179
  "auth.acl.features.documents.templates.manage": "Zarządzaj szablonami dokumentów",
178
180
  "auth.acl.features.documents.view": "Wyświetl dokumenty",
181
+ "auth.acl.features.ecommerce.branding.manage": "Zarządzanie brandingiem sklepu",
182
+ "auth.acl.features.ecommerce.channels.manage": "Zarządzanie powiązaniami kanałów sklepu",
183
+ "auth.acl.features.ecommerce.domains.manage": "Zarządzanie powiązaniami domen sklepu",
184
+ "auth.acl.features.ecommerce.stores.manage": "Zarządzanie sklepami",
185
+ "auth.acl.features.ecommerce.stores.view": "Wyświetlanie sklepów",
179
186
  "auth.acl.features.entities.definitions.manage": "Zarządzaj definicjami pól własnych",
180
187
  "auth.acl.features.entities.definitions.view": "Wyświetl definicje pól własnych",
181
188
  "auth.acl.features.entities.records.manage": "Zarządzaj rekordami",
@@ -424,6 +431,7 @@
424
431
  "auth.acl.modules.dictionaries": "Współdzielone słowniki",
425
432
  "auth.acl.modules.directory": "Katalog najemców i organizacji",
426
433
  "auth.acl.modules.documents": "Dokumenty",
434
+ "auth.acl.modules.ecommerce": "Sklepy e-commerce",
427
435
  "auth.acl.modules.entities": "Własne encje i pola",
428
436
  "auth.acl.modules.eudr": "Zgodność z EUDR",
429
437
  "auth.acl.modules.example": "Moduł przykładowy",
@@ -47,11 +47,14 @@ The default pipeline emits `catalog.pricing.resolve.before|after` events. `prici
47
47
 
48
48
  ### Price selection order
49
49
 
50
+ Candidate rows are those `matchesContext` admits. When `ctx.priceKindId` is set, that means rows of that kind **plus** rows of any promotional kind (`priceKind.isPromotion === true`, populated relation required), and `buildPriceRowFilter` mirrors this with a `priceKind.isPromotion` relation clause. Keep the two in sync: the filter MUST admit every row the matcher admits.
51
+
50
52
  When multiple price rows match the same context, `selectBestPrice` resolves ties in this order:
51
53
 
52
54
  1. **Score** (descending) — `custom` > `promotion` > `tier` > `regular`, plus additional points for variant, offer, channel, user, group, and customer scoping. See `scorePrice` for the full rubric.
53
- 2. **`startsAt`** (descending) — when scores tie, the row with the more recent `startsAt` wins.
54
- 3. **`minQuantity`** — direction depends on whether the tied rows share the same resolved kind:
55
+ 2. **Buyer order** — when scores tie and both rows are customer-scoped, the row whose `customerId` comes earlier in `ctx.customerIds` (person before company) wins.
56
+ 3. **`startsAt`** (descending) — when scores tie, the row with the more recent `startsAt` wins.
57
+ 4. **`minQuantity`** — direction depends on whether the tied rows share the same resolved kind:
55
58
  - **Same kind** (e.g. tier vs tier): **descending** — the row with the larger `minQuantity` wins. This implements the standard volume-discount semantic: for `qty=50` with tiers `minQty=10` ($9) and `minQty=50` ($8), the `minQty=50` row applies (issue #1706).
56
59
  - **Different kinds** (e.g. promotion vs tier): **ascending** — the row with the smaller `minQuantity` wins. The `+1 for minQuantity > 1` bonus in `scorePrice` can pull a lower-base kind up to the same total as a higher-base kind (e.g. tier `minQty=3` = 3+1 vs promotion `minQty=1` = 4). Ascending across kinds preserves the kind precedence in those collisions.
57
60
 
@@ -30,7 +30,14 @@ export const features = [
30
30
  module: 'catalog',
31
31
  dependsOn: ['catalog.products.view', 'currencies.view'],
32
32
  },
33
+ { id: 'catalog.settings.view', title: 'View catalog settings', module: 'catalog' },
33
34
  { id: 'catalog.settings.manage', title: 'Manage catalog settings', module: 'catalog' },
35
+ {
36
+ id: 'catalog.price_history.view',
37
+ title: 'View catalog price history',
38
+ module: 'catalog',
39
+ dependsOn: ['catalog.products.view'],
40
+ },
34
41
  ]
35
42
 
36
43
  export default features
@@ -0,0 +1,204 @@
1
+ import { NextResponse } from 'next/server'
2
+ import { z } from 'zod'
3
+ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
4
+ import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
5
+ import { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
6
+ import {
7
+ bridgeLegacyGuard,
8
+ runMutationGuards,
9
+ type MutationGuard,
10
+ } from '@open-mercato/shared/lib/crud/mutation-guard-registry'
11
+ import { getAllMutationGuardInstances } from '@open-mercato/shared/lib/crud/mutation-guard-store'
12
+ import { createLogger } from '@open-mercato/shared/lib/logger'
13
+ import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
14
+ import type { ModuleConfigService } from '@open-mercato/core/modules/configs/lib/module-config-service'
15
+ import type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'
16
+ import { omnibusConfigPatchSchema, type OmnibusConfigPatch } from '../../../data/validators'
17
+ import { OMNIBUS_CONFIG_MODULE_ID, OMNIBUS_CONFIG_NAME, omnibusConfigSchema, type OmnibusConfig } from '../../../lib/omnibusTypes'
18
+ import {
19
+ buildOmnibusFieldErrors,
20
+ evaluateOmnibusConfig,
21
+ invalidOmnibusConfig,
22
+ mergeOmnibusConfig,
23
+ parseStoredOmnibusConfig,
24
+ type OmnibusConfigEvaluation,
25
+ } from '../../../lib/omnibusConfig'
26
+ import { invalidateOmnibusTenantCache, resolveOmnibusCache } from '../../../lib/omnibusCache'
27
+
28
+ const logger = createLogger('catalog')
29
+
30
+ const OMNIBUS_CONFIG_RESOURCE_KIND = 'catalog.settings'
31
+
32
+ const OMNIBUS_CONFIG_READ_FEATURES = ['catalog.settings.view', 'catalog.settings.manage'] as const
33
+
34
+ export const metadata = {
35
+ GET: { requireAuth: true },
36
+ PATCH: { requireAuth: true, requireFeatures: ['catalog.settings.manage'] },
37
+ }
38
+
39
+ function resolveUserFeatures(auth: unknown): string[] {
40
+ const features = (auth as { features?: unknown })?.features
41
+ if (!Array.isArray(features)) return []
42
+ return features.filter((value): value is string => typeof value === 'string')
43
+ }
44
+
45
+ async function readStoredConfig(service: ModuleConfigService, tenantId: string): Promise<OmnibusConfig | null> {
46
+ const raw = await service.getValue<unknown>(OMNIBUS_CONFIG_MODULE_ID, OMNIBUS_CONFIG_NAME, { scope: { tenantId } })
47
+ const config = parseStoredOmnibusConfig(raw)
48
+ if (raw !== null && raw !== undefined && !config) {
49
+ logger.warn('[internal] catalog omnibus stored config is invalid; treating it as unset', { tenantId })
50
+ }
51
+ return config
52
+ }
53
+
54
+ function evaluatePatch(existing: OmnibusConfig | null, payload: unknown): OmnibusConfigEvaluation & { patch?: OmnibusConfigPatch } {
55
+ const parsed = omnibusConfigPatchSchema.safeParse(payload)
56
+ if (!parsed.success) return invalidOmnibusConfig(buildOmnibusFieldErrors(parsed.error.issues))
57
+ return { ...evaluateOmnibusConfig(mergeOmnibusConfig(existing, parsed.data)), patch: parsed.data }
58
+ }
59
+
60
+ export async function GET(req: Request) {
61
+ try {
62
+ const auth = await getAuthFromRequest(req)
63
+ if (!auth || !auth.tenantId) {
64
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
65
+ }
66
+ const container = await createRequestContainer()
67
+ const rbacService = container.resolve('rbacService') as RbacService
68
+ const scope = { tenantId: auth.tenantId, organizationId: auth.orgId ?? null }
69
+ let canRead = false
70
+ for (const feature of OMNIBUS_CONFIG_READ_FEATURES) {
71
+ if (await rbacService.userHasAllFeatures(auth.sub, [feature], scope)) {
72
+ canRead = true
73
+ break
74
+ }
75
+ }
76
+ if (!canRead) return NextResponse.json({ error: 'Forbidden' }, { status: 403 })
77
+ const service = container.resolve('moduleConfigService') as ModuleConfigService
78
+ const config = await readStoredConfig(service, auth.tenantId)
79
+ return NextResponse.json(config ?? {})
80
+ } catch (err) {
81
+ if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
82
+ logger.error('catalog.config.omnibus.GET failed', { err })
83
+ return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
84
+ }
85
+ }
86
+
87
+ export async function PATCH(req: Request) {
88
+ try {
89
+ const auth = await getAuthFromRequest(req)
90
+ if (!auth || !auth.tenantId) {
91
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
92
+ }
93
+ const tenantId = auth.tenantId
94
+ const organizationId = auth.orgId ?? null
95
+
96
+ let body: unknown
97
+ try {
98
+ body = await req.json()
99
+ } catch {
100
+ return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 })
101
+ }
102
+
103
+ const container = await createRequestContainer()
104
+ const service = container.resolve('moduleConfigService') as ModuleConfigService
105
+ const existing = await readStoredConfig(service, tenantId)
106
+
107
+ let evaluation = evaluatePatch(existing, body)
108
+ if (!evaluation.ok) return NextResponse.json(evaluation.body, { status: evaluation.status })
109
+
110
+ const legacyGuard = bridgeLegacyGuard(container)
111
+ const guards: MutationGuard[] = [...getAllMutationGuardInstances()]
112
+ if (legacyGuard) guards.push(legacyGuard)
113
+ const guardInput = {
114
+ tenantId,
115
+ organizationId,
116
+ userId: auth.sub ?? '',
117
+ resourceKind: OMNIBUS_CONFIG_RESOURCE_KIND,
118
+ resourceId: OMNIBUS_CONFIG_NAME,
119
+ operation: 'update' as const,
120
+ requestMethod: req.method,
121
+ requestHeaders: req.headers,
122
+ }
123
+ const guardResult = await runMutationGuards(
124
+ guards,
125
+ { ...guardInput, mutationPayload: evaluation.patch ?? null },
126
+ { userFeatures: resolveUserFeatures(auth) },
127
+ )
128
+ if (!guardResult.ok) {
129
+ return NextResponse.json(guardResult.errorBody ?? { error: 'Operation blocked by guard' }, {
130
+ status: guardResult.errorStatus ?? 422,
131
+ })
132
+ }
133
+ if (guardResult.modifiedPayload) {
134
+ evaluation = evaluatePatch(existing, { ...evaluation.patch, ...guardResult.modifiedPayload })
135
+ if (!evaluation.ok) return NextResponse.json(evaluation.body, { status: evaluation.status })
136
+ }
137
+
138
+ const nextConfig = evaluation.config
139
+ // optimistic-lock-exempt: single tenant-scoped config blob merged server-side; no per-record version to compare
140
+ await service.setValue(OMNIBUS_CONFIG_MODULE_ID, OMNIBUS_CONFIG_NAME, nextConfig, { tenantId })
141
+ await invalidateOmnibusTenantCache(resolveOmnibusCache(container), tenantId)
142
+
143
+ for (const callback of guardResult.afterSuccessCallbacks) {
144
+ if (!callback.guard.afterSuccess) continue
145
+ try {
146
+ await callback.guard.afterSuccess({ ...guardInput, metadata: callback.metadata ?? null })
147
+ } catch (callbackError) {
148
+ logger.error('Mutation guard afterSuccess callback failed', {
149
+ component: 'catalog.config.omnibus',
150
+ guardId: callback.guard.id,
151
+ err: callbackError,
152
+ })
153
+ }
154
+ }
155
+
156
+ return NextResponse.json(nextConfig)
157
+ } catch (err) {
158
+ if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
159
+ logger.error('catalog.config.omnibus.PATCH failed', { err })
160
+ return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
161
+ }
162
+ }
163
+
164
+ const errorSchema = z.object({ error: z.string() }).passthrough()
165
+
166
+ const invalidConfigSchema = z.object({
167
+ error: z.literal('Invalid config'),
168
+ details: z.object({ fieldErrors: z.record(z.string(), z.array(z.string())) }),
169
+ })
170
+
171
+ const backfillRequiredSchema = z.object({
172
+ field: z.literal('enabled'),
173
+ error: z.literal('backfill_required_before_enable'),
174
+ channels: z.array(z.string()),
175
+ })
176
+
177
+ export const openApi: OpenApiRouteDoc = {
178
+ tag: 'Catalog',
179
+ summary: 'Omnibus price-reference configuration',
180
+ methods: {
181
+ GET: {
182
+ summary: 'Read the tenant Omnibus configuration',
183
+ description: 'Returns the tenant-scoped Omnibus configuration with defaults applied, or an empty object when it has never been configured.',
184
+ tags: ['Catalog'],
185
+ responses: [
186
+ { status: 200, description: 'Tenant Omnibus configuration ({} when unset)', schema: omnibusConfigSchema.partial() },
187
+ ],
188
+ errors: [{ status: 401, description: 'Unauthorized', schema: errorSchema }],
189
+ },
190
+ PATCH: {
191
+ summary: 'Update the tenant Omnibus configuration',
192
+ description:
193
+ 'Shallow-merges the provided top-level fields into the stored tenant configuration (a provided `channels` map replaces the stored one; `null` clears `defaultPresentedPriceKindId`). Member-state derogation fields and `backfillCoverage` are rejected. Enabling requires a resolvable presented price kind and completed backfill coverage for every in-scope EU channel.',
194
+ tags: ['Catalog'],
195
+ requestBody: { schema: omnibusConfigPatchSchema },
196
+ responses: [{ status: 200, description: 'Merged Omnibus configuration', schema: omnibusConfigSchema }],
197
+ errors: [
198
+ { status: 400, description: 'Invalid JSON body or invalid config', schema: invalidConfigSchema },
199
+ { status: 401, description: 'Unauthorized', schema: errorSchema },
200
+ { status: 422, description: 'Backfill required before enabling, or blocked by a mutation guard', schema: backfillRequiredSchema },
201
+ ],
202
+ },
203
+ },
204
+ }